Skip to content

Commit e81ae29

Browse files
committed
Allow SGX to be run with different commands through the host
1 parent ca660cf commit e81ae29

File tree

2 files changed

+81
-158
lines changed

2 files changed

+81
-158
lines changed

prove_block.sh

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ elif [ "$proof" == "sp1" ]; then
3131
elif [ "$proof" == "sgx" ]; then
3232
proofParam='{
3333
"instance_id": 123,
34+
"setup": true,
35+
"bootstrap": true,
36+
"prove": true,
3437
"input_path": null
3538
}'
3639
elif [ "$proof" == "risc0" ]; then

provers/sgx/prover/src/lib.rs

+78-158
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ use tokio::{process::Command, sync::OnceCell};
2424
#[derive(Clone, Debug, Serialize, Deserialize)]
2525
pub struct SgxParam {
2626
pub instance_id: u64,
27+
pub setup: bool,
28+
pub bootstrap: bool,
29+
pub prove: bool,
2730
pub input_path: Option<PathBuf>,
2831
}
2932

@@ -40,11 +43,7 @@ pub const INPUT_FILE_NAME: &str = "input.bin";
4043
pub const CONFIG: &str = "../../provers/sgx/config";
4144

4245
static GRAMINE_MANIFEST_TEMPLATE: Lazy<OnceCell<PathBuf>> = Lazy::new(OnceCell::new);
43-
static INPUT_FILE: Lazy<OnceCell<PathBuf>> = Lazy::new(OnceCell::new);
4446
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);
4847

4948
pub struct SgxProver;
5049

@@ -67,49 +66,22 @@ impl Prover for SgxProver {
6766
println!("WARNING: running SGX in direct mode!");
6867
}
6968

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);
7076
// 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)
11385
let gramine_cmd = || -> Command {
11486
let mut cmd = if direct_mode {
11587
Command::new("gramine-direct")
@@ -122,30 +94,30 @@ impl Prover for SgxProver {
12294
cmd
12395
};
12496

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+
}
142101

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?;
146105
}
147106

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+
}
149121
}
150122

151123
fn instance_hash(pi: ProtocolInstance) -> B256 {
@@ -163,50 +135,12 @@ impl Prover for SgxProver {
163135
}
164136
}
165137

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> {
178139
// Create required directories
179140
let directories = ["secrets", "config"];
180141
for dir in directories {
181142
create_dir_all(cur_dir.join(dir)).unwrap();
182143
}
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-
}
210144
if direct_mode {
211145
// Copy dummy files in direct mode
212146
let files = ["attestation_type", "quote", "user_report_data"];
@@ -218,33 +152,6 @@ async fn prepare_working_directory(
218152
.unwrap();
219153
}
220154
}
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;
248155

249156
// Generate the manifest
250157
let mut cmd = Command::new("gramine-manifest");
@@ -285,43 +192,61 @@ pub async fn execute(
285192
.map_err(|e| format!("Could not sign manfifest: {}", e))?;
286193
}
287194

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+
}
300197

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
303207
.arg("bootstrap")
304208
.output()
305209
.await
306210
.map_err(|e| format!("Could not run SGX guest boostrap: {}", e))?;
307211
print_output(&output, "Sgx bootstrap");
308212

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+
309235
// Prove
310-
let output = gramine_cmd()
236+
let output = gramine_cmd
311237
.arg("one-shot")
312238
.arg("--sgx-instance-id")
313-
.arg(param.instance_id.to_string())
239+
.arg(instance_id.to_string())
314240
.output()
315241
.await
316242
.map_err(|e| format!("Could not run SGX guest prover: {}", e))?;
317243
print_output(&output, "Sgx execution");
318-
319244
if !output.status.success() {
320245
// inc_sgx_error(req.block_number);
321-
return Err(output.status.to_string());
246+
return ProverResult::Err(ProverError::GuestError(output.status.to_string()));
322247
}
323248

324-
parse_sgx_result(output.stdout)
249+
Ok(parse_sgx_result(output.stdout)?)
325250
}
326251

327252
fn parse_sgx_result(output: Vec<u8>) -> ProverResult<SgxResponse, String> {
@@ -363,12 +288,7 @@ fn print_output(output: &Output, name: &str) {
363288

364289
fn print_dirs() {
365290
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()] {
372292
println!(" {:?}", dir);
373293
}
374294
}

0 commit comments

Comments
 (0)