@@ -24,6 +24,9 @@ use tokio::{process::Command, sync::OnceCell};
24
24
#[ derive( Clone , Debug , Serialize , Deserialize ) ]
25
25
pub struct SgxParam {
26
26
pub instance_id : u64 ,
27
+ pub setup : bool ,
28
+ pub bootstrap : bool ,
29
+ pub prove : bool ,
27
30
pub input_path : Option < PathBuf > ,
28
31
}
29
32
@@ -40,11 +43,7 @@ pub const INPUT_FILE_NAME: &str = "input.bin";
40
43
pub const CONFIG : & str = "../../provers/sgx/config" ;
41
44
42
45
static GRAMINE_MANIFEST_TEMPLATE : Lazy < OnceCell < PathBuf > > = Lazy :: new ( OnceCell :: new) ;
43
- static INPUT_FILE : Lazy < OnceCell < PathBuf > > = Lazy :: new ( OnceCell :: new) ;
44
46
static PRIVATE_KEY : Lazy < OnceCell < PathBuf > > = Lazy :: new ( OnceCell :: new) ;
45
- static ATTESTATION_TYPE : Lazy < OnceCell < PathBuf > > = Lazy :: new ( OnceCell :: new) ;
46
- static QUOTE : Lazy < OnceCell < PathBuf > > = Lazy :: new ( OnceCell :: new) ;
47
- static USER_REPORT_DATA : Lazy < OnceCell < PathBuf > > = Lazy :: new ( OnceCell :: new) ;
48
47
49
48
pub struct SgxProver ;
50
49
@@ -67,49 +66,22 @@ impl Prover for SgxProver {
67
66
println ! ( "WARNING: running SGX in direct mode!" ) ;
68
67
}
69
68
69
+ // The working directory
70
+ let cur_dir = env:: current_exe ( )
71
+ . expect ( "Fail to get current directory" )
72
+ . parent ( )
73
+ . unwrap ( )
74
+ . to_path_buf ( ) ;
75
+ println ! ( "Current directory: {:?}\n " , cur_dir) ;
70
76
// Working paths
71
- let cur_dir = prepare_working_directory ( direct_mode, input. clone ( ) , param. input_path ) . await ;
72
-
73
- // Generate the manifest
74
- let mut cmd = Command :: new ( "gramine-manifest" ) ;
75
- let output = cmd
76
- . current_dir ( cur_dir. clone ( ) )
77
- . arg ( "-Dlog_level=error" )
78
- . arg ( "-Darch_libdir=/lib/x86_64-linux-gnu/" )
79
- . arg ( format ! (
80
- "-Ddirect_mode={}" ,
81
- if direct_mode { "1" } else { "0" }
82
- ) )
83
- . arg ( GRAMINE_MANIFEST_TEMPLATE . get ( ) . unwrap ( ) )
84
- . arg ( "sgx-guest.manifest" )
85
- . output ( )
86
- . await
87
- . map_err ( |e| format ! ( "Could not generate manfifest: {}" , e) ) ?;
88
-
89
- print_output ( & output, "Generate manifest" ) ;
90
-
91
- if !direct_mode {
92
- // Generate a private key
93
- let mut cmd = Command :: new ( "gramine-sgx-gen-private-key" ) ;
94
- cmd. current_dir ( cur_dir. clone ( ) )
95
- . arg ( "-f" )
96
- . output ( )
97
- . await
98
- . map_err ( |e| format ! ( "Could not generate SGX private key: {}" , e) ) ?;
99
-
100
- // Sign the manifest
101
- let mut cmd = Command :: new ( "gramine-sgx-sign" ) ;
102
- cmd. current_dir ( cur_dir. clone ( ) )
103
- . arg ( "--manifest" )
104
- . arg ( "sgx-guest.manifest" )
105
- . arg ( "--output" )
106
- . arg ( "sgx-guest.manifest.sgx" )
107
- . output ( )
108
- . await
109
- . map_err ( |e| format ! ( "Could not sign manfifest: {}" , e) ) ?;
110
- }
111
-
112
- // Form gramine command
77
+ PRIVATE_KEY
78
+ . get_or_init ( || async { cur_dir. join ( "secrets" ) . join ( "priv.key" ) } )
79
+ . await ;
80
+ GRAMINE_MANIFEST_TEMPLATE
81
+ . get_or_init ( || async { cur_dir. join ( CONFIG ) . join ( "raiko-guest.manifest.template" ) } )
82
+ . await ;
83
+
84
+ // The gramine command (gramine or gramine-direct for testing in non-SGX environment)
113
85
let gramine_cmd = || -> Command {
114
86
let mut cmd = if direct_mode {
115
87
Command :: new ( "gramine-direct" )
@@ -122,30 +94,30 @@ impl Prover for SgxProver {
122
94
cmd
123
95
} ;
124
96
125
- // Bootstrap new private key
126
- let output = gramine_cmd ( )
127
- . arg ( "bootstrap" )
128
- . output ( )
129
- . await
130
- . map_err ( |e| format ! ( "Could not run SGX guest boostrap: {}" , e) ) ?;
131
- print_output ( & output, "Sgx bootstrap" ) ;
132
-
133
- // Prove
134
- let output = gramine_cmd ( )
135
- . arg ( "one-shot" )
136
- . arg ( "--sgx-instance-id" )
137
- . arg ( param. instance_id . to_string ( ) )
138
- . output ( )
139
- . await
140
- . map_err ( |e| format ! ( "Could not run SGX guest prover: {}" , e) ) ?;
141
- print_output ( & output, "Sgx execution" ) ;
97
+ // Setup: run this once while setting up your SGX instance
98
+ if param. setup {
99
+ setup ( & cur_dir, direct_mode) . await ?;
100
+ }
142
101
143
- if !output . status . success ( ) {
144
- // inc_sgx_error(req.block_number);
145
- return ProverResult :: Err ( ProverError :: GuestError ( output . status . to_string ( ) ) ) ;
102
+ // Boostrap: run this each time a new keypair for proving needs to be generated
103
+ if param . bootstrap {
104
+ bootstrap ( & mut gramine_cmd ( ) ) . await ? ;
146
105
}
147
106
148
- Ok ( parse_sgx_result ( output. stdout ) ?)
107
+ // Prove: run for each block
108
+ if param. prove {
109
+ prove (
110
+ & mut gramine_cmd ( ) ,
111
+ & cur_dir,
112
+ input,
113
+ param. instance_id ,
114
+ param. input_path ,
115
+ )
116
+ . await
117
+ } else {
118
+ // Dummy proof: it's ok when only setup/bootstrap was requested
119
+ Ok ( SgxResponse :: default ( ) )
120
+ }
149
121
}
150
122
151
123
fn instance_hash ( pi : ProtocolInstance ) -> B256 {
@@ -163,50 +135,12 @@ impl Prover for SgxProver {
163
135
}
164
136
}
165
137
166
- async fn prepare_working_directory (
167
- direct_mode : bool ,
168
- input : GuestInput ,
169
- cached_input : Option < PathBuf > ,
170
- ) -> PathBuf {
171
- let cur_dir = env:: current_exe ( )
172
- . expect ( "Fail to get current directory" )
173
- . parent ( )
174
- . unwrap ( )
175
- . to_path_buf ( ) ;
176
- println ! ( "Current directory: {:?}\n " , cur_dir) ;
177
-
138
+ async fn setup ( cur_dir : & PathBuf , direct_mode : bool ) -> ProverResult < SgxResponse , String > {
178
139
// Create required directories
179
140
let directories = [ "secrets" , "config" ] ;
180
141
for dir in directories {
181
142
create_dir_all ( cur_dir. join ( dir) ) . unwrap ( ) ;
182
143
}
183
- GRAMINE_MANIFEST_TEMPLATE
184
- . get_or_init ( || async { cur_dir. join ( CONFIG ) . join ( "raiko-guest.manifest.template" ) } )
185
- . await ;
186
- // If cached input file is not provided
187
- // write the input to a file that will be read by the SGX instance
188
- let input_path = match cached_input {
189
- Some ( path) => path. clone ( ) ,
190
- None => {
191
- let path = cur_dir. join ( INPUT_FILE_NAME ) ;
192
- bincode:: serialize_into ( File :: create ( & path) . expect ( "Unable to open file" ) , & input)
193
- . expect ( "Unable to serialize input" ) ;
194
- path
195
- }
196
- } ;
197
- // TODO(Ceilia): support long running ra-tls server
198
- INPUT_FILE . get_or_init ( || async { input_path } ) . await ;
199
- PRIVATE_KEY
200
- . get_or_init ( || async { cur_dir. join ( "secrets" ) . join ( "priv.key" ) } )
201
- . await ;
202
- // Bootstrap
203
- // First delete the private key if it already exists
204
- let path = cur_dir. join ( "secrets" ) . join ( "priv.key" ) ;
205
- if path. exists ( ) {
206
- if let Err ( e) = remove_file ( & path) {
207
- println ! ( "Error deleting file: {}" , e) ;
208
- }
209
- }
210
144
if direct_mode {
211
145
// Copy dummy files in direct mode
212
146
let files = [ "attestation_type" , "quote" , "user_report_data" ] ;
@@ -218,33 +152,6 @@ async fn prepare_working_directory(
218
152
. unwrap ( ) ;
219
153
}
220
154
}
221
- ATTESTATION_TYPE
222
- . get_or_init ( || async { cur_dir. join ( "attestation_type" ) } )
223
- . await ;
224
- QUOTE . get_or_init ( || async { cur_dir. join ( "quote" ) } ) . await ;
225
- USER_REPORT_DATA
226
- . get_or_init ( || async { cur_dir. join ( "user_report_data" ) } )
227
- . await ;
228
- cur_dir
229
- }
230
-
231
- pub async fn execute (
232
- input : GuestInput ,
233
- _output : GuestOutput ,
234
- param : SgxParam ,
235
- ) -> Result < SgxResponse , String > {
236
- // Support both SGX and the direct backend for testing
237
- let direct_mode = match env:: var ( "SGX_DIRECT" ) {
238
- Ok ( value) => value == "1" ,
239
- Err ( _) => false ,
240
- } ;
241
- // Print a warning when running in direct mode
242
- if direct_mode {
243
- println ! ( "WARNING: running SGX in direct mode!" ) ;
244
- }
245
-
246
- // Working paths
247
- let cur_dir = prepare_working_directory ( direct_mode, input. clone ( ) , param. input_path ) . await ;
248
155
249
156
// Generate the manifest
250
157
let mut cmd = Command :: new ( "gramine-manifest" ) ;
@@ -285,43 +192,61 @@ pub async fn execute(
285
192
. map_err ( |e| format ! ( "Could not sign manfifest: {}" , e) ) ?;
286
193
}
287
194
288
- // Form gramine command
289
- let gramine_cmd = || -> Command {
290
- let mut cmd = if direct_mode {
291
- Command :: new ( "gramine-direct" )
292
- } else {
293
- let mut cmd = Command :: new ( "sudo" ) ;
294
- cmd. arg ( "gramine-sgx" ) ;
295
- cmd
296
- } ;
297
- cmd. current_dir ( & cur_dir) . arg ( ELF_NAME ) ;
298
- cmd
299
- } ;
195
+ Ok ( SgxResponse :: default ( ) )
196
+ }
300
197
301
- // Bootstrap new private key
302
- let output = gramine_cmd ( )
198
+ async fn bootstrap ( gramine_cmd : & mut Command ) -> ProverResult < SgxResponse , String > {
199
+ // Bootstrap with new private key for signing proofs
200
+ // First delete the private key if it already exists
201
+ if PRIVATE_KEY . get ( ) . unwrap ( ) . exists ( ) {
202
+ if let Err ( e) = remove_file ( & PRIVATE_KEY . get ( ) . unwrap ( ) ) {
203
+ println ! ( "Error deleting file: {}" , e) ;
204
+ }
205
+ }
206
+ let output = gramine_cmd
303
207
. arg ( "bootstrap" )
304
208
. output ( )
305
209
. await
306
210
. map_err ( |e| format ! ( "Could not run SGX guest boostrap: {}" , e) ) ?;
307
211
print_output ( & output, "Sgx bootstrap" ) ;
308
212
213
+ Ok ( SgxResponse :: default ( ) )
214
+ }
215
+
216
+ async fn prove (
217
+ gramine_cmd : & mut Command ,
218
+ cur_dir : & PathBuf ,
219
+ input : GuestInput ,
220
+ instance_id : u64 ,
221
+ input_path : Option < PathBuf > ,
222
+ ) -> ProverResult < SgxResponse , ProverError > {
223
+ // If cached input file is not provided
224
+ // write the input to a file that will be read by the SGX instance
225
+ let _input_path = match input_path {
226
+ Some ( path) => path. clone ( ) ,
227
+ None => {
228
+ let path = cur_dir. join ( INPUT_FILE_NAME ) ;
229
+ bincode:: serialize_into ( File :: create ( & path) . expect ( "Unable to open file" ) , & input)
230
+ . expect ( "Unable to serialize input" ) ;
231
+ path
232
+ }
233
+ } ;
234
+
309
235
// Prove
310
- let output = gramine_cmd ( )
236
+ let output = gramine_cmd
311
237
. arg ( "one-shot" )
312
238
. arg ( "--sgx-instance-id" )
313
- . arg ( param . instance_id . to_string ( ) )
239
+ . arg ( instance_id. to_string ( ) )
314
240
. output ( )
315
241
. await
316
242
. map_err ( |e| format ! ( "Could not run SGX guest prover: {}" , e) ) ?;
317
243
print_output ( & output, "Sgx execution" ) ;
318
-
319
244
if !output. status . success ( ) {
320
245
// inc_sgx_error(req.block_number);
321
- return Err ( output. status . to_string ( ) ) ;
246
+ return ProverResult :: Err ( ProverError :: GuestError ( output. status . to_string ( ) ) ) ;
322
247
}
323
248
324
- parse_sgx_result ( output. stdout )
249
+ Ok ( parse_sgx_result ( output. stdout ) ? )
325
250
}
326
251
327
252
fn parse_sgx_result ( output : Vec < u8 > ) -> ProverResult < SgxResponse , String > {
@@ -363,12 +288,7 @@ fn print_output(output: &Output, name: &str) {
363
288
364
289
fn print_dirs ( ) {
365
290
println ! ( "SGX output directories:" ) ;
366
- for dir in [
367
- PRIVATE_KEY . get ( ) . unwrap ( ) ,
368
- ATTESTATION_TYPE . get ( ) . unwrap ( ) ,
369
- QUOTE . get ( ) . unwrap ( ) ,
370
- USER_REPORT_DATA . get ( ) . unwrap ( ) ,
371
- ] {
291
+ for dir in [ PRIVATE_KEY . get ( ) . unwrap ( ) ] {
372
292
println ! ( " {:?}" , dir) ;
373
293
}
374
294
}
0 commit comments