1+ use anyhow:: Context as _;
12use oracle_provider:: ZkEENonDeterminismSource ;
2- use std:: path:: Path ;
3+ use std:: path:: { Path , PathBuf } ;
34use std:: sync:: { Arc , Mutex } ;
45use std:: time:: Instant ;
56
@@ -11,6 +12,8 @@ pub struct ProofResult {
1112}
1213
1314pub struct Prover {
15+ app_bin_path : PathBuf ,
16+ worker_threads : Option < usize > ,
1417 inner : Arc < Mutex < execution_utils:: unrolled_gpu:: UnrolledProver > > ,
1518}
1619
@@ -22,19 +25,15 @@ impl std::fmt::Debug for Prover {
2225
2326impl Prover {
2427 pub fn new ( app_bin_path : & Path , worker_threads : Option < usize > ) -> anyhow:: Result < Self > {
25- let base_path = strip_bin_suffix ( app_bin_path) ?;
26- let mut configuration =
27- execution_utils:: gpu_prover:: execution:: prover:: ExecutionProverConfiguration :: default ( ) ;
28- if let Some ( threads) = worker_threads {
29- configuration. max_thread_pool_threads = Some ( threads) ;
30- configuration. replay_worker_threads_count = threads;
31- }
32- let inner = execution_utils:: unrolled_gpu:: UnrolledProver :: new (
33- & base_path,
34- configuration,
35- execution_utils:: unrolled_gpu:: UnrolledProverLevel :: RecursionUnified ,
36- ) ;
28+ let inner = create_unrolled_prover ( app_bin_path, worker_threads) . with_context ( || {
29+ format ! (
30+ "failed to create unrolled prover with app binary at {:?}" ,
31+ app_bin_path
32+ )
33+ } ) ?;
3734 Ok ( Self {
35+ app_bin_path : app_bin_path. to_path_buf ( ) ,
36+ worker_threads,
3837 inner : Arc :: new ( Mutex :: new ( inner) ) ,
3938 } )
4039 }
@@ -48,11 +47,33 @@ impl Prover {
4847
4948 let inner = self . inner . clone ( ) ;
5049
51- let ( proof , cycles ) = tokio:: task:: spawn_blocking ( move || {
50+ let future_result = tokio:: task:: spawn_blocking ( move || {
5251 let prover = inner. lock ( ) . unwrap ( ) ;
5352 prover. prove ( block_number, oracle)
5453 } )
55- . await ?;
54+ . await ;
55+ let ( proof, cycles) = match future_result {
56+ Ok ( result) => result,
57+ Err ( err) => {
58+ let panic_msg = crate :: utils:: extract_panic_message ( err) ;
59+
60+ // If prover panics, it is not safe to use it again, since some of threads may be poisoned/dead.
61+ // We need to re-instantiate it.
62+ {
63+ let mut inner = self . inner . lock ( ) . unwrap ( ) ;
64+ // If we cannot reinstantiate the prover for some reason, we cannot do much -- better to panic.
65+ * inner = create_unrolled_prover ( self . app_bin_path . as_path ( ) , self . worker_threads ) . expect (
66+ "failed to re-instantiate prover after panic; prover app binary path is invalid" ,
67+ ) ;
68+ }
69+
70+ return Err ( anyhow:: anyhow!(
71+ "Prover task panicked for the block {}: {}" ,
72+ block_number,
73+ panic_msg
74+ ) ) ;
75+ }
76+ } ;
5677
5778 let proving_time_secs = start. elapsed ( ) . as_secs_f64 ( ) ;
5879 let proof_bytes = bincode:: serde:: encode_to_vec ( & proof, bincode:: config:: standard ( ) ) ?;
@@ -74,3 +95,23 @@ fn strip_bin_suffix(path: &Path) -> anyhow::Result<String> {
7495 Ok ( path_str. to_string ( ) )
7596 }
7697}
98+
99+ fn create_unrolled_prover (
100+ app_bin_path : & Path ,
101+ worker_threads : Option < usize > ,
102+ ) -> anyhow:: Result < execution_utils:: unrolled_gpu:: UnrolledProver > {
103+ let base_path = strip_bin_suffix ( app_bin_path) ?;
104+ let mut configuration =
105+ execution_utils:: gpu_prover:: execution:: prover:: ExecutionProverConfiguration :: default ( ) ;
106+ if let Some ( threads) = worker_threads {
107+ configuration. max_thread_pool_threads = Some ( threads) ;
108+ configuration. replay_worker_threads_count = threads;
109+ }
110+
111+ let unrolled_prover = execution_utils:: unrolled_gpu:: UnrolledProver :: new (
112+ & base_path,
113+ configuration,
114+ execution_utils:: unrolled_gpu:: UnrolledProverLevel :: RecursionUnified ,
115+ ) ;
116+ Ok ( unrolled_prover)
117+ }
0 commit comments