@@ -21,13 +21,14 @@ use sp1_sdk::{
21
21
} ;
22
22
use sp1_sdk:: { HashableKey , ProverClient , SP1Stdin } ;
23
23
use std:: { borrow:: BorrowMut , env, sync:: Arc , time:: Duration } ;
24
- use tracing:: { debug, error , info} ;
24
+ use tracing:: { debug, info} ;
25
25
26
26
mod proof_verify;
27
27
use proof_verify:: remote_contract_verify:: verify_sol_by_contract_call;
28
28
29
29
pub const ELF : & [ u8 ] = include_bytes ! ( "../../guest/elf/sp1-guest" ) ;
30
30
pub const AGGREGATION_ELF : & [ u8 ] = include_bytes ! ( "../../guest/elf/sp1-aggregation" ) ;
31
+ pub const BATCH_ELF : & [ u8 ] = include_bytes ! ( "../../guest/elf/sp1-batch" ) ;
31
32
32
33
#[ serde_as]
33
34
#[ derive( Clone , Debug , Serialize , Deserialize ) ]
@@ -110,6 +111,7 @@ struct Sp1ProverClient {
110
111
//TODO: use prover object to save such local storage members.
111
112
static BLOCK_PROOF_CLIENT : Lazy < DashMap < ProverMode , Sp1ProverClient > > = Lazy :: new ( DashMap :: new) ;
112
113
static AGGREGATION_CLIENT : Lazy < DashMap < ProverMode , Sp1ProverClient > > = Lazy :: new ( DashMap :: new) ;
114
+ static BATCH_PROOF_CLIENT : Lazy < DashMap < ProverMode , Sp1ProverClient > > = Lazy :: new ( DashMap :: new) ;
113
115
114
116
impl Prover for Sp1Prover {
115
117
async fn run (
@@ -197,8 +199,8 @@ impl Prover for Sp1Prover {
197
199
. await ?;
198
200
}
199
201
info ! (
200
- "Sp1 Prover: block {:?} - proof id {proof_id :?}" ,
201
- output. header. number
202
+ "Sp1: network proof id: {:?} for block { :?}" ,
203
+ proof_id , output. header. number
202
204
) ;
203
205
network_client
204
206
. wait_proof ( proof_id. clone ( ) , Some ( Duration :: from_secs ( 3600 ) ) )
@@ -319,7 +321,7 @@ impl Prover for Sp1Prover {
319
321
stdin. write_proof ( * block_proof, stark_vk. clone ( ) ) ;
320
322
}
321
323
_ => {
322
- error ! ( "unsupported proof type for aggregation: {sp1_proof:?}" ) ;
324
+ panic ! ( "unsupported proof type for aggregation: {sp1_proof:?}" ) ;
323
325
}
324
326
}
325
327
}
@@ -387,6 +389,7 @@ impl Prover for Sp1Prover {
387
389
. map_err ( |e| {
388
390
ProverError :: GuestError ( format ! ( "Sp1: network proving failed: {e}" ) )
389
391
} ) ?;
392
+ info ! ( "Sp1: network proof id: {proof_id:?} for aggregation" ) ;
390
393
network_client
391
394
. wait_proof ( proof_id. clone ( ) , Some ( Duration :: from_secs ( 3600 ) ) )
392
395
. await
@@ -429,12 +432,146 @@ impl Prover for Sp1Prover {
429
432
}
430
433
431
434
async fn batch_run (
432
- _input : GuestBatchInput ,
433
- _output : & GuestBatchOutput ,
434
- _config : & ProverConfig ,
435
- _store : Option < & mut dyn IdWrite > ,
435
+ input : GuestBatchInput ,
436
+ output : & GuestBatchOutput ,
437
+ config : & ProverConfig ,
438
+ id_store : Option < & mut dyn IdWrite > ,
436
439
) -> ProverResult < Proof > {
437
- unimplemented ! ( ) ;
440
+ let param = Sp1Param :: deserialize ( config. get ( "sp1" ) . unwrap ( ) ) . unwrap ( ) ;
441
+ let mode = param. prover . clone ( ) . unwrap_or_else ( get_env_mock) ;
442
+
443
+ println ! ( "batch_run param: {param:?}" ) ;
444
+ let mut stdin = SP1Stdin :: new ( ) ;
445
+ stdin. write ( & input) ;
446
+
447
+ let Sp1ProverClient {
448
+ client,
449
+ pk,
450
+ vk,
451
+ network_client,
452
+ } = BATCH_PROOF_CLIENT
453
+ . entry ( mode. clone ( ) )
454
+ . or_insert_with ( || {
455
+ let network_client = Arc :: new ( ProverClient :: builder ( ) . network ( ) . build ( ) ) ;
456
+ let base_client: Box < dyn SP1ProverTrait < CpuProverComponents > > = match mode {
457
+ ProverMode :: Mock => Box :: new ( ProverClient :: builder ( ) . mock ( ) . build ( ) ) ,
458
+ ProverMode :: Local => Box :: new ( ProverClient :: builder ( ) . cpu ( ) . build ( ) ) ,
459
+ ProverMode :: Network => Box :: new ( ProverClient :: builder ( ) . network ( ) . build ( ) ) ,
460
+ } ;
461
+
462
+ let client = Arc :: new ( base_client) ;
463
+ let ( pk, vk) = client. setup ( BATCH_ELF ) ;
464
+ info ! (
465
+ "new client and setup() for batch {:?}." ,
466
+ input. taiko. batch_id
467
+ ) ;
468
+ Sp1ProverClient {
469
+ client,
470
+ network_client,
471
+ pk,
472
+ vk,
473
+ }
474
+ } )
475
+ . clone ( ) ;
476
+
477
+ info ! (
478
+ "Sp1 Prover: batch {:?} with vk {:?}, output.hash: {}" ,
479
+ input. taiko. batch_id,
480
+ vk. bytes32( ) ,
481
+ output. hash
482
+ ) ;
483
+
484
+ let prove_result = if !matches ! ( mode, ProverMode :: Network ) {
485
+ debug ! ( "Proving locally with recursion mode: {:?}" , param. recursion) ;
486
+ let prove_mode = match param. recursion {
487
+ RecursionMode :: Core => SP1ProofMode :: Core ,
488
+ RecursionMode :: Compressed => SP1ProofMode :: Compressed ,
489
+ RecursionMode :: Plonk => SP1ProofMode :: Plonk ,
490
+ } ;
491
+ client
492
+ . prove ( & pk, & stdin, prove_mode)
493
+ . map_err ( |e| ProverError :: GuestError ( format ! ( "Sp1: local proving failed: {e}" ) ) ) ?
494
+ } else {
495
+ let proof_id = network_client
496
+ . prove ( & pk, & stdin)
497
+ . mode ( param. recursion . clone ( ) . into ( ) )
498
+ . cycle_limit ( 1_000_000_000_000 )
499
+ . skip_simulation ( true )
500
+ . strategy ( FulfillmentStrategy :: Reserved )
501
+ . request_async ( )
502
+ . await
503
+ . map_err ( |e| {
504
+ ProverError :: GuestError ( format ! ( "Sp1: requesting proof failed: {e}" ) )
505
+ } ) ?;
506
+ if let Some ( id_store) = id_store {
507
+ id_store
508
+ . store_id (
509
+ (
510
+ input. taiko . chain_spec . chain_id ,
511
+ input. taiko . batch_id ,
512
+ output. hash ,
513
+ ProofType :: Sp1 as u8 ,
514
+ ) ,
515
+ proof_id. clone ( ) . to_string ( ) ,
516
+ )
517
+ . await ?;
518
+ }
519
+ info ! (
520
+ "Sp1 Prover: batch {:?} - proof id {proof_id:?}" ,
521
+ input. taiko. batch_id
522
+ ) ;
523
+ network_client
524
+ . wait_proof ( proof_id. clone ( ) , Some ( Duration :: from_secs ( 3600 ) ) )
525
+ . await
526
+ . map_err ( |e| ProverError :: GuestError ( format ! ( "Sp1: network proof failed {e:?}" ) ) ) ?
527
+ } ;
528
+
529
+ let proof_bytes = match param. recursion {
530
+ RecursionMode :: Compressed => {
531
+ info ! ( "Compressed proof is used in aggregation mode only" ) ;
532
+ vec ! [ ]
533
+ }
534
+ _ => prove_result. bytes ( ) ,
535
+ } ;
536
+ if param. verify && !proof_bytes. is_empty ( ) {
537
+ let time = Measurement :: start ( "verify" , false ) ;
538
+ let pi_hash = prove_result
539
+ . clone ( )
540
+ . borrow_mut ( )
541
+ . public_values
542
+ . read :: < [ u8 ; 32 ] > ( ) ;
543
+ let fixture = RaikoProofFixture {
544
+ vkey : vk. bytes32 ( ) ,
545
+ public_values : B256 :: from_slice ( & pi_hash) . to_string ( ) ,
546
+ proof : proof_bytes. clone ( ) ,
547
+ } ;
548
+
549
+ verify_sol_by_contract_call ( & fixture) . await ?;
550
+ time. stop_with ( "==> Verification complete" ) ;
551
+ }
552
+
553
+ let proof_string = ( !proof_bytes. is_empty ( ) ) . then_some (
554
+ // 0x + 64 bytes of the vkey + the proof
555
+ // vkey itself contains 0x prefix
556
+ format ! (
557
+ "{}{}" ,
558
+ vk. bytes32( ) ,
559
+ reth_primitives:: hex:: encode( proof_bytes)
560
+ ) ,
561
+ ) ;
562
+
563
+ info ! (
564
+ "Sp1 Prover: batch {:?} completed! proof: {proof_string:?}" ,
565
+ input. taiko. batch_id,
566
+ ) ;
567
+ Ok :: < _ , ProverError > (
568
+ Sp1Response {
569
+ proof : proof_string,
570
+ sp1_proof : Some ( prove_result) ,
571
+ vkey : Some ( vk. clone ( ) ) ,
572
+ }
573
+ . into ( ) ,
574
+ )
438
575
}
439
576
}
440
577
0 commit comments