feat: move sgx utility functions to sgx/utils module for better organization
This commit is contained in:
parent
bb861fe817
commit
4d17ba6667
@ -3,8 +3,9 @@ use crate::sgx::config::{validate_yaml, DeteeCliExt};
|
||||
use crate::sgx::grpc_brain::{delete_app, new_app};
|
||||
use crate::sgx::grpc_dtpm::{attest_and_send_config, get_config_from_enclave};
|
||||
use crate::sgx::packaging::package_enclave;
|
||||
use crate::sgx::utils::{fetch_config_and_mr_enclave, override_envs_and_args_launch_config};
|
||||
use crate::sgx::AppDeleteResponse;
|
||||
use crate::utils::{block_on, fetch_config_and_mr_enclave, override_envs_and_args_launch_config};
|
||||
use crate::utils::block_on;
|
||||
use crate::{cli_print, SimpleOutput};
|
||||
use clap::ArgMatches;
|
||||
use detee_shared::sgx::types::brain::AppDeployConfig;
|
||||
|
@ -7,7 +7,8 @@ use detee_shared::sgx::types::brain::AppDeployConfig;
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::utils::{self, calculate_nanolp_for_app, sign_request};
|
||||
use crate::sgx::utils::calculate_nanolp_for_app;
|
||||
use crate::utils::{self, sign_request};
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
|
@ -12,7 +12,8 @@ use detee_shared::sgx::{
|
||||
types::dtpm::DtpmConfig,
|
||||
};
|
||||
|
||||
use crate::{config::Config, utils::hratls_url_and_mr_enclave_from_app_id};
|
||||
use crate::config::Config;
|
||||
use crate::sgx::utils::hratls_url_and_mr_enclave_from_app_id;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
|
@ -16,6 +16,7 @@ pub mod config;
|
||||
pub mod grpc_brain;
|
||||
pub mod grpc_dtpm;
|
||||
pub mod packaging;
|
||||
pub mod utils;
|
||||
|
||||
#[derive(Tabled, Debug, Serialize, Deserialize)]
|
||||
pub struct AppContract {
|
||||
|
129
src/sgx/utils.rs
Normal file
129
src/sgx/utils.rs
Normal file
@ -0,0 +1,129 @@
|
||||
use crate::constants::HRATLS_APP_PORT;
|
||||
use crate::sgx::grpc_brain::list_apps;
|
||||
use detee_shared::sgx::types::dtpm::DtpmConfig;
|
||||
use detee_shared::sgx::types::dtpm::EnvironmentEntry;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
Reqwest(#[from] reqwest::Error),
|
||||
#[error(transparent)]
|
||||
Serde(#[from] serde_yaml::Error),
|
||||
#[error("{0}")]
|
||||
PublicPackage(std::string::String),
|
||||
}
|
||||
|
||||
pub async fn hratls_url_and_mr_enclave_from_app_id(app_id: &str) -> (String, Option<[u8; 32]>) {
|
||||
let app_contracts = list_apps().await.expect("Could not get App contracts");
|
||||
let app_contract = app_contracts.iter().find(|contract| contract.uuid == app_id);
|
||||
if app_contract.is_none() {
|
||||
eprintln!("Could not find App contract with ID: {}", app_id);
|
||||
std::process::exit(1);
|
||||
}
|
||||
let app_contract = app_contract.unwrap();
|
||||
let mr_enclave = app_contract
|
||||
.public_package_mr_enclave
|
||||
.clone()
|
||||
.filter(|vec| vec.len() == 32)
|
||||
.and_then(|vec| vec.try_into().ok());
|
||||
|
||||
let public_ip = app_contract.public_ipv4.clone();
|
||||
let dtpm_port = app_contract
|
||||
.mapped_ports
|
||||
.iter()
|
||||
.find(|port| port.app_port == HRATLS_APP_PORT)
|
||||
.unwrap()
|
||||
.host_port;
|
||||
|
||||
(format!("https://{public_ip}:{dtpm_port}"), mr_enclave)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct PublicIndex {
|
||||
packages: Vec<PackageElement>,
|
||||
}
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct PackageElement {
|
||||
package_url: String,
|
||||
launch_config_url: String,
|
||||
mr_enclave: [u8; 32],
|
||||
}
|
||||
|
||||
pub async fn fetch_config_and_mr_enclave(
|
||||
package_url: &str,
|
||||
) -> Result<([u8; 32], DtpmConfig), Error> {
|
||||
let public_packages_index =
|
||||
reqwest::get("https://registry.detee.ltd/sgx/public_packages_index.yaml")
|
||||
.await?
|
||||
.text()
|
||||
.await?;
|
||||
|
||||
let index = serde_yaml::from_str::<PublicIndex>(&public_packages_index)?;
|
||||
|
||||
let index_package_entry =
|
||||
index.packages.iter().find(|package| package.package_url == package_url).ok_or(
|
||||
Error::PublicPackage("mr_enclave not found for this public package".to_string()),
|
||||
)?;
|
||||
|
||||
let PackageElement { launch_config_url, mr_enclave, .. } = index_package_entry;
|
||||
|
||||
let launch_config_str = reqwest::get(launch_config_url).await?.text().await?;
|
||||
|
||||
let launch_config = serde_yaml::from_str::<DtpmConfig>(&launch_config_str)?;
|
||||
|
||||
Ok((*mr_enclave, launch_config))
|
||||
}
|
||||
|
||||
pub fn calculate_nanolp_for_app(
|
||||
vcpus: u32,
|
||||
memory_mb: u32,
|
||||
disk_size_mb: u32,
|
||||
hours: u64,
|
||||
node_price: u64,
|
||||
) -> u64 {
|
||||
// this calculation needs to match the calculation of the network
|
||||
let total_units =
|
||||
(vcpus as f64 * 5f64) + (memory_mb as f64 / 200f64) + (disk_size_mb as f64 / 10000f64);
|
||||
let locked_nano = (hours as f64 * 60f64 * total_units * node_price as f64) as u64;
|
||||
println!(
|
||||
"Node price: {}/unit/minute. Total Units for hardware requested: {:.4}. Locking {} LP (offering the App for {} hours).",
|
||||
node_price as f64 / 1_000_000_000.0,
|
||||
total_units,
|
||||
locked_nano as f64 / 1_000_000_000.0,
|
||||
hours
|
||||
);
|
||||
locked_nano
|
||||
}
|
||||
|
||||
pub fn override_envs_and_args_launch_config(
|
||||
launch_config: &mut DtpmConfig,
|
||||
envs: Vec<String>,
|
||||
args: Vec<String>,
|
||||
) {
|
||||
for env in envs {
|
||||
let mut env = env.split("=");
|
||||
let key = env.next().expect("environment variable must be in the format 'key=value'");
|
||||
let value =
|
||||
env.next().expect("environment variable pair must be in the format 'key=value'");
|
||||
|
||||
if launch_config.environments.iter().find(|env| env.name == key).is_some() {
|
||||
let existing_env =
|
||||
launch_config.environments.iter_mut().find(|env| env.name == key).unwrap();
|
||||
|
||||
existing_env.name = key.to_string();
|
||||
existing_env.value = value.to_string();
|
||||
} else {
|
||||
let mut new_env = EnvironmentEntry::default();
|
||||
|
||||
new_env.name = key.to_string();
|
||||
new_env.value = value.to_string();
|
||||
|
||||
launch_config.environments.push(new_env);
|
||||
}
|
||||
}
|
||||
|
||||
for arg in args {
|
||||
launch_config.child_processes.first_mut().unwrap().arguments.push(arg);
|
||||
}
|
||||
}
|
125
src/utils.rs
125
src/utils.rs
@ -1,9 +1,4 @@
|
||||
use crate::config::Config;
|
||||
use crate::constants::HRATLS_APP_PORT;
|
||||
use crate::sgx::grpc_brain::list_apps;
|
||||
use detee_shared::sgx::types::dtpm::DtpmConfig;
|
||||
use detee_shared::sgx::types::dtpm::EnvironmentEntry;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tonic::metadata::errors::InvalidMetadataValue;
|
||||
use tonic::metadata::AsciiMetadataValue;
|
||||
use tonic::Request;
|
||||
@ -14,12 +9,6 @@ pub enum Error {
|
||||
ConfigError(#[from] crate::config::Error),
|
||||
#[error(transparent)]
|
||||
InternalError(#[from] InvalidMetadataValue),
|
||||
#[error(transparent)]
|
||||
Reqwest(#[from] reqwest::Error),
|
||||
#[error(transparent)]
|
||||
Serde(#[from] serde_yaml::Error),
|
||||
#[error("{0}")]
|
||||
PublicPackage(std::string::String),
|
||||
}
|
||||
|
||||
pub fn block_on<F>(future: F) -> F::Output
|
||||
@ -42,117 +31,3 @@ pub fn sign_request<T: std::fmt::Debug>(req: T) -> Result<Request<T>, Error> {
|
||||
req.metadata_mut().insert("request-signature", signature);
|
||||
Ok(req)
|
||||
}
|
||||
|
||||
pub async fn hratls_url_and_mr_enclave_from_app_id(app_id: &str) -> (String, Option<[u8; 32]>) {
|
||||
let app_contracts = list_apps().await.expect("Could not get App contracts");
|
||||
let app_contract = app_contracts.iter().find(|contract| contract.uuid == app_id);
|
||||
if app_contract.is_none() {
|
||||
eprintln!("Could not find App contract with ID: {}", app_id);
|
||||
std::process::exit(1);
|
||||
}
|
||||
let app_contract = app_contract.unwrap();
|
||||
let mr_enclave = app_contract
|
||||
.public_package_mr_enclave
|
||||
.clone()
|
||||
.filter(|vec| vec.len() == 32)
|
||||
.and_then(|vec| vec.try_into().ok());
|
||||
|
||||
let public_ip = app_contract.public_ipv4.clone();
|
||||
let dtpm_port = app_contract
|
||||
.mapped_ports
|
||||
.iter()
|
||||
.find(|port| port.app_port == HRATLS_APP_PORT)
|
||||
.unwrap()
|
||||
.host_port;
|
||||
|
||||
(format!("https://{public_ip}:{dtpm_port}"), mr_enclave)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct PublicIndex {
|
||||
packages: Vec<PackageElement>,
|
||||
}
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct PackageElement {
|
||||
package_url: String,
|
||||
launch_config_url: String,
|
||||
mr_enclave: [u8; 32],
|
||||
}
|
||||
|
||||
pub async fn fetch_config_and_mr_enclave(
|
||||
package_url: &str,
|
||||
) -> Result<([u8; 32], DtpmConfig), Error> {
|
||||
let public_packages_index =
|
||||
reqwest::get("https://registry.detee.ltd/sgx/public_packages_index.yaml")
|
||||
.await?
|
||||
.text()
|
||||
.await?;
|
||||
|
||||
let index = serde_yaml::from_str::<PublicIndex>(&public_packages_index)?;
|
||||
|
||||
let index_package_entry =
|
||||
index.packages.iter().find(|package| package.package_url == package_url).ok_or(
|
||||
Error::PublicPackage("mr_enclave not found for this public package".to_string()),
|
||||
)?;
|
||||
|
||||
let PackageElement { launch_config_url, mr_enclave, .. } = index_package_entry;
|
||||
|
||||
let launch_config_str = reqwest::get(launch_config_url).await?.text().await?;
|
||||
|
||||
let launch_config = serde_yaml::from_str::<DtpmConfig>(&launch_config_str)?;
|
||||
|
||||
Ok((*mr_enclave, launch_config))
|
||||
}
|
||||
|
||||
pub fn calculate_nanolp_for_app(
|
||||
vcpus: u32,
|
||||
memory_mb: u32,
|
||||
disk_size_mb: u32,
|
||||
hours: u64,
|
||||
node_price: u64,
|
||||
) -> u64 {
|
||||
// this calculation needs to match the calculation of the network
|
||||
let total_units =
|
||||
(vcpus as f64 * 5f64) + (memory_mb as f64 / 200f64) + (disk_size_mb as f64 / 10000f64);
|
||||
let locked_nano = (hours as f64 * 60f64 * total_units * node_price as f64) as u64;
|
||||
println!(
|
||||
"Node price: {}/unit/minute. Total Units for hardware requested: {:.4}. Locking {} LP (offering the App for {} hours).",
|
||||
node_price as f64 / 1_000_000_000.0,
|
||||
total_units,
|
||||
locked_nano as f64 / 1_000_000_000.0,
|
||||
hours
|
||||
);
|
||||
locked_nano
|
||||
}
|
||||
|
||||
pub fn override_envs_and_args_launch_config(
|
||||
launch_config: &mut DtpmConfig,
|
||||
envs: Vec<String>,
|
||||
args: Vec<String>,
|
||||
) {
|
||||
for env in envs {
|
||||
let mut env = env.split("=");
|
||||
let key = env.next().expect("environment variable must be in the format 'key=value'");
|
||||
let value =
|
||||
env.next().expect("environment variable pair must be in the format 'key=value'");
|
||||
|
||||
if launch_config.environments.iter().find(|env| env.name == key).is_some() {
|
||||
let existing_env =
|
||||
launch_config.environments.iter_mut().find(|env| env.name == key).unwrap();
|
||||
|
||||
existing_env.name = key.to_string();
|
||||
existing_env.value = value.to_string();
|
||||
} else {
|
||||
let mut new_env = EnvironmentEntry::default();
|
||||
|
||||
new_env.name = key.to_string();
|
||||
new_env.value = value.to_string();
|
||||
|
||||
launch_config.environments.push(new_env);
|
||||
}
|
||||
}
|
||||
|
||||
for arg in args {
|
||||
launch_config.child_processes.first_mut().unwrap().arguments.push(arg);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user