@@ -748,12 +748,10 @@ pub async fn handle_wormhole_command(
748748 Ok ( ( ) )
749749 } ,
750750 WormholeCommands :: Aggregate { proofs, output } => aggregate_proofs ( proofs, output) . await ,
751- WormholeCommands :: VerifyAggregated { proof } => {
752- verify_aggregated_proof ( proof, node_url) . await
753- } ,
754- WormholeCommands :: ParseProof { proof, aggregated, verify } => {
755- parse_proof_file ( proof, aggregated, verify) . await
756- } ,
751+ WormholeCommands :: VerifyAggregated { proof } =>
752+ verify_aggregated_proof ( proof, node_url) . await ,
753+ WormholeCommands :: ParseProof { proof, aggregated, verify } =>
754+ parse_proof_file ( proof, aggregated, verify) . await ,
757755 WormholeCommands :: Multiround {
758756 num_proofs,
759757 rounds,
@@ -2398,8 +2396,6 @@ async fn parse_proof_file(
23982396/// A pending wormhole output that can be used as input for the next dissolve layer.
23992397#[ derive( Debug , Clone ) ]
24002398struct DissolveOutput {
2401- /// The wormhole address that received the funds
2402- address : SubxtAccountId ,
24032399 /// The secret used to derive the wormhole address
24042400 secret : [ u8 ; 32 ] ,
24052401 /// Amount in planck
@@ -2408,6 +2404,8 @@ struct DissolveOutput {
24082404 transfer_count : u64 ,
24092405 /// Funding account (sender)
24102406 funding_account : SubxtAccountId ,
2407+ /// Block hash where the transfer was recorded (needed for storage proof)
2408+ proof_block_hash : subxt:: utils:: H256 ,
24112409}
24122410
24132411/// Dissolve a large wormhole deposit into many small outputs for better privacy.
@@ -2531,11 +2529,11 @@ async fn run_dissolve(
25312529 . map_err ( |e| crate :: error:: QuantusError :: Generic ( format ! ( "Event decode error: {}" , e) ) ) ?;
25322530
25332531 let mut current_outputs = vec ! [ DissolveOutput {
2534- address: wormhole_address,
25352532 secret: initial_secret. secret,
25362533 amount,
25372534 transfer_count: event. transfer_count,
25382535 funding_account: funding_account. clone( ) ,
2536+ proof_block_hash: block_hash,
25392537 } ] ;
25402538
25412539 log_success ! ( " Funded 1 wormhole address with {}" , format_balance( amount) ) ;
@@ -2565,12 +2563,6 @@ async fn run_dissolve(
25652563 next_secrets. push ( derive_wormhole_secret ( & wallet. mnemonic , layer, i + 1 ) ?) ;
25662564 }
25672565
2568- // Get current block for all proofs in this layer
2569- let proof_block = at_best_block ( & quantus_client) . await . map_err ( |e| {
2570- crate :: error:: QuantusError :: Generic ( format ! ( "Failed to get block: {}" , e) )
2571- } ) ?;
2572- let proof_block_hash = proof_block. hash ( ) ;
2573-
25742566 // Process inputs in batches of ≤16 (aggregation batch size)
25752567 let batch_size = agg_config. num_leaf_proofs ;
25762568 let mut all_next_outputs: Vec < DissolveOutput > = Vec :: new ( ) ;
@@ -2588,6 +2580,11 @@ async fn run_dissolve(
25882580 let mut proof_files = Vec :: new ( ) ;
25892581 let proof_gen_start = std:: time:: Instant :: now ( ) ;
25902582
2583+ // All inputs in a batch must use the same block for proof generation.
2584+ // Use the proof_block_hash from the first input (all inputs in a batch
2585+ // were created in the same verification block from the previous layer).
2586+ let batch_proof_block_hash = batch_inputs[ 0 ] . proof_block_hash ;
2587+
25912588 for ( i, input) in batch_inputs. iter ( ) . enumerate ( ) {
25922589 let global_idx = batch_start + i;
25932590 let exit_1_idx = global_idx * 2 ;
@@ -2612,7 +2609,7 @@ async fn run_dissolve(
26122609 & hex:: encode ( input. secret ) ,
26132610 input. amount ,
26142611 & assignment,
2615- & format ! ( "0x{}" , hex:: encode( proof_block_hash . 0 ) ) ,
2612+ & format ! ( "0x{}" , hex:: encode( batch_proof_block_hash . 0 ) ) ,
26162613 input. transfer_count ,
26172614 & format ! ( "0x{}" , hex:: encode( input. funding_account. 0 ) ) ,
26182615 & proof_file,
@@ -2643,7 +2640,8 @@ async fn run_dissolve(
26432640 log_success ! ( " Verified in block 0x{}" , hex:: encode( verification_block. 0 ) ) ;
26442641
26452642 // Collect next layer's outputs from the transfer events
2646- for ( i, input) in batch_inputs. iter ( ) . enumerate ( ) {
2643+ // Use the verification_block as the proof_block_hash for the next layer
2644+ for ( i, _input) in batch_inputs. iter ( ) . enumerate ( ) {
26472645 let global_idx = batch_start + i;
26482646 let exit_1_idx = global_idx * 2 ;
26492647 let exit_2_idx = global_idx * 2 + 1 ;
@@ -2663,11 +2661,11 @@ async fn run_dissolve(
26632661 } ) ?;
26642662
26652663 all_next_outputs. push ( DissolveOutput {
2666- address : SubxtAccountId ( target_address. address ) ,
26672664 secret : target_address. secret ,
26682665 amount : event. amount ,
26692666 transfer_count : event. transfer_count ,
2670- funding_account : input. address . clone ( ) ,
2667+ funding_account : event. from . clone ( ) ,
2668+ proof_block_hash : verification_block,
26712669 } ) ;
26722670 }
26732671 }
@@ -2867,8 +2865,8 @@ mod tests {
28672865 let output_medium = compute_output_amount ( input_medium, VOLUME_FEE_BPS ) ;
28682866 assert_eq ! ( output_medium, 9990 ) ;
28692867 assert ! (
2870- ( output_medium as u64 ) * 10000
2871- <= ( input_medium as u64 ) * ( 10000 - VOLUME_FEE_BPS as u64 )
2868+ ( output_medium as u64 ) * 10000 <=
2869+ ( input_medium as u64 ) * ( 10000 - VOLUME_FEE_BPS as u64 )
28722870 ) ;
28732871
28742872 // Large amounts near u32::MAX
0 commit comments