@@ -4,6 +4,7 @@ use crate::{
44 quantus_subxt:: { self as quantus_node, api:: wormhole} ,
55 } ,
66 cli:: {
7+ address_format:: { bytes_to_quantus_ss58, slice_to_quantus_ss58} ,
78 common:: { submit_transaction, ExecutionMode } ,
89 send:: get_balance,
910 } ,
@@ -880,10 +881,11 @@ async fn aggregate_proofs(
880881 // De-quantize to show actual amount that will be minted
881882 let dequantized_amount =
882883 ( account_data. summed_output_amount as u128 ) * SCALE_DOWN_FACTOR ;
884+ let ss58_address = slice_to_quantus_ss58 ( exit_bytes) ;
883885 log_print ! (
884886 " [{}] {} -> {} quantized ({} planck = {})" ,
885887 idx,
886- hex :: encode ( exit_bytes ) ,
888+ ss58_address ,
887889 account_data. summed_output_amount,
888890 dequantized_amount,
889891 format_balance( dequantized_amount)
@@ -1304,8 +1306,13 @@ fn print_multiround_config(
13041306
13051307/// Execute initial transfers from wallet to wormhole addresses (round 1 only).
13061308///
1307- /// Sends all transfers in a single batched extrinsic using `utility.batch()`,
1308- /// then parses the `NativeTransferred` events to extract transfer info for proof generation.
1309+ /// Sends all transfers in a single batched extrinsic using `utility.batch()`.
1310+ /// Transfer counts are queried from chain storage (not events) to determine the
1311+ /// `transfer_count` for each recipient, which is needed for proof generation.
1312+ ///
1313+ /// Note: We query `TransferCount` storage BEFORE submitting the batch because
1314+ /// the transfer_count in the proof must be the value at the time of transfer
1315+ /// (i.e., before the increment that happens during `record_transfer`).
13091316async fn execute_initial_transfers (
13101317 quantus_client : & QuantusClient ,
13111318 wallet : & MultiroundWalletContext ,
@@ -1349,6 +1356,33 @@ async fn execute_initial_transfers(
13491356
13501357 log_print ! ( " Submitting batch of {} transfers..." , num_proofs) ;
13511358
1359+ // Query transfer counts BEFORE submitting the batch.
1360+ // The transfer_count used in the proof is the count at the time of transfer,
1361+ // which equals the count before the transfer (since it increments after).
1362+ let client = quantus_client. client ( ) ;
1363+ let mut transfer_counts_before: Vec < u64 > = Vec :: with_capacity ( num_proofs) ;
1364+ for secret in secrets. iter ( ) {
1365+ let wormhole_address = SubxtAccountId ( secret. address ) ;
1366+ let count = client
1367+ . storage ( )
1368+ . at_latest ( )
1369+ . await
1370+ . map_err ( |e| {
1371+ crate :: error:: QuantusError :: Generic ( format ! ( "Failed to get storage: {}" , e) )
1372+ } ) ?
1373+ . fetch ( & quantus_node:: api:: storage ( ) . wormhole ( ) . transfer_count ( wormhole_address) )
1374+ . await
1375+ . map_err ( |e| {
1376+ crate :: error:: QuantusError :: Generic ( format ! (
1377+ "Failed to fetch transfer count for {}: {}" ,
1378+ hex:: encode( secret. address) ,
1379+ e
1380+ ) )
1381+ } ) ?
1382+ . unwrap_or ( 0 ) ;
1383+ transfer_counts_before. push ( count) ;
1384+ }
1385+
13521386 submit_transaction (
13531387 quantus_client,
13541388 & quantum_keypair,
@@ -1359,40 +1393,20 @@ async fn execute_initial_transfers(
13591393 . await
13601394 . map_err ( |e| crate :: error:: QuantusError :: Generic ( format ! ( "Batch transfer failed: {}" , e) ) ) ?;
13611395
1362- // Get the block and find all NativeTransferred events
1363- let client = quantus_client. client ( ) ;
1396+ // Get the block hash for the transfer info (any recent block works since we use storage)
13641397 let block = at_best_block ( quantus_client)
13651398 . await
13661399 . map_err ( |e| crate :: error:: QuantusError :: Generic ( format ! ( "Failed to get block: {}" , e) ) ) ?;
13671400 let block_hash = block. hash ( ) ;
13681401
1369- let events_api =
1370- client. events ( ) . at ( block_hash) . await . map_err ( |e| {
1371- crate :: error:: QuantusError :: Generic ( format ! ( "Failed to get events: {}" , e) )
1372- } ) ?;
1373-
1374- // Match each secret's wormhole address to its NativeTransferred event
1402+ // Build transfer info using the transfer counts we captured before the batch
13751403 let funding_account: SubxtAccountId = SubxtAccountId ( wallet. keypair . to_account_id_32 ( ) . into ( ) ) ;
13761404 let mut transfers = Vec :: with_capacity ( num_proofs) ;
13771405
13781406 for ( i, secret) in secrets. iter ( ) . enumerate ( ) {
1379- let event = events_api
1380- . find :: < wormhole:: events:: NativeTransferred > ( )
1381- . find ( |e| if let Ok ( evt) = e { evt. to . 0 == secret. address } else { false } )
1382- . ok_or_else ( || {
1383- crate :: error:: QuantusError :: Generic ( format ! (
1384- "No NativeTransferred event found for wormhole address {} (proof {})" ,
1385- hex:: encode( secret. address) ,
1386- i + 1
1387- ) )
1388- } ) ?
1389- . map_err ( |e| {
1390- crate :: error:: QuantusError :: Generic ( format ! ( "Event decode error: {}" , e) )
1391- } ) ?;
1392-
13931407 transfers. push ( TransferInfo {
13941408 block_hash,
1395- transfer_count : event . transfer_count ,
1409+ transfer_count : transfer_counts_before [ i ] ,
13961410 amount : partition_amounts[ i] ,
13971411 wormhole_address : SubxtAccountId ( secret. address ) ,
13981412 funding_account : funding_account. clone ( ) ,
@@ -1440,25 +1454,27 @@ async fn generate_round_proofs(
14401454 log_print ! ( " Random output partition:" ) ;
14411455 for ( i, assignment) in output_assignments. iter ( ) . enumerate ( ) {
14421456 let amt1_planck = ( assignment. output_amount_1 as u128 ) * SCALE_DOWN_FACTOR ;
1457+ let ss58_1 = bytes_to_quantus_ss58 ( & assignment. exit_account_1 ) ;
14431458 if assignment. output_amount_2 > 0 {
14441459 let amt2_planck = ( assignment. output_amount_2 as u128 ) * SCALE_DOWN_FACTOR ;
1460+ let ss58_2 = bytes_to_quantus_ss58 ( & assignment. exit_account_2 ) ;
14451461 log_print ! (
1446- " Proof {}: {} ({}) -> 0x{}... , {} ({}) -> 0x{}... " ,
1462+ " Proof {}: {} ({}) -> {} , {} ({}) -> {} " ,
14471463 i + 1 ,
14481464 assignment. output_amount_1,
14491465 format_balance( amt1_planck) ,
1450- hex :: encode ( & assignment . exit_account_1 [ .. 4 ] ) ,
1466+ ss58_1 ,
14511467 assignment. output_amount_2,
14521468 format_balance( amt2_planck) ,
1453- hex :: encode ( & assignment . exit_account_2 [ .. 4 ] )
1469+ ss58_2
14541470 ) ;
14551471 } else {
14561472 log_print ! (
1457- " Proof {}: {} ({}) -> 0x{}... " ,
1473+ " Proof {}: {} ({}) -> {} " ,
14581474 i + 1 ,
14591475 assignment. output_amount_1,
14601476 format_balance( amt1_planck) ,
1461- hex :: encode ( & assignment . exit_account_1 [ .. 4 ] )
1477+ ss58_1
14621478 ) ;
14631479 }
14641480 }
@@ -1978,6 +1994,25 @@ async fn verify_aggregated_and_get_events(
19781994 // Verify locally before submitting on-chain
19791995 log_verbose ! ( "Verifying aggregated proof locally before on-chain submission..." ) ;
19801996 let bins_dir = Path :: new ( "generated-bins" ) ;
1997+
1998+ // Log circuit binary hashes for debugging
1999+ let common_bytes = std:: fs:: read ( bins_dir. join ( "aggregated_common.bin" ) ) . map_err ( |e| {
2000+ crate :: error:: QuantusError :: Generic ( format ! ( "Failed to read aggregated_common.bin: {}" , e) )
2001+ } ) ?;
2002+ let verifier_bytes = std:: fs:: read ( bins_dir. join ( "aggregated_verifier.bin" ) ) . map_err ( |e| {
2003+ crate :: error:: QuantusError :: Generic ( format ! (
2004+ "Failed to read aggregated_verifier.bin: {}" ,
2005+ e
2006+ ) )
2007+ } ) ?;
2008+ println ! (
2009+ "[quantus-cli] Circuit binaries: common_bytes.len={}, verifier_bytes.len={}, common_hash={}, verifier_hash={}" ,
2010+ common_bytes. len( ) ,
2011+ verifier_bytes. len( ) ,
2012+ hex:: encode( blake3:: hash( & common_bytes) . as_bytes( ) ) ,
2013+ hex:: encode( blake3:: hash( & verifier_bytes) . as_bytes( ) ) ,
2014+ ) ;
2015+
19812016 let verifier = WormholeVerifier :: new_from_files (
19822017 & bins_dir. join ( "aggregated_verifier.bin" ) ,
19832018 & bins_dir. join ( "aggregated_common.bin" ) ,
@@ -2030,11 +2065,11 @@ async fn verify_aggregated_and_get_events(
20302065 // Log minted amounts
20312066 log_print ! ( " Tokens minted (from NativeTransferred events):" ) ;
20322067 for ( idx, transfer) in transfer_events. iter ( ) . enumerate ( ) {
2033- let to_hex = hex :: encode ( transfer. to . 0 ) ;
2068+ let ss58_address = bytes_to_quantus_ss58 ( & transfer. to . 0 ) ;
20342069 log_print ! (
20352070 " [{}] {} -> {} planck ({})" ,
20362071 idx,
2037- to_hex ,
2072+ ss58_address ,
20382073 transfer. amount,
20392074 format_balance( transfer. amount)
20402075 ) ;
0 commit comments