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_brain::{delete_app, new_app};
|
||||||
use crate::sgx::grpc_dtpm::{attest_and_send_config, get_config_from_enclave};
|
use crate::sgx::grpc_dtpm::{attest_and_send_config, get_config_from_enclave};
|
||||||
use crate::sgx::packaging::package_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::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 crate::{cli_print, SimpleOutput};
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use detee_shared::sgx::types::brain::AppDeployConfig;
|
use detee_shared::sgx::types::brain::AppDeployConfig;
|
||||||
|
@ -7,7 +7,8 @@ use detee_shared::sgx::types::brain::AppDeployConfig;
|
|||||||
use tokio_stream::StreamExt;
|
use tokio_stream::StreamExt;
|
||||||
|
|
||||||
use crate::config::Config;
|
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)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -12,7 +12,8 @@ use detee_shared::sgx::{
|
|||||||
types::dtpm::DtpmConfig,
|
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)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -16,6 +16,7 @@ pub mod config;
|
|||||||
pub mod grpc_brain;
|
pub mod grpc_brain;
|
||||||
pub mod grpc_dtpm;
|
pub mod grpc_dtpm;
|
||||||
pub mod packaging;
|
pub mod packaging;
|
||||||
|
pub mod utils;
|
||||||
|
|
||||||
#[derive(Tabled, Debug, Serialize, Deserialize)]
|
#[derive(Tabled, Debug, Serialize, Deserialize)]
|
||||||
pub struct AppContract {
|
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::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::errors::InvalidMetadataValue;
|
||||||
use tonic::metadata::AsciiMetadataValue;
|
use tonic::metadata::AsciiMetadataValue;
|
||||||
use tonic::Request;
|
use tonic::Request;
|
||||||
@ -14,12 +9,6 @@ pub enum Error {
|
|||||||
ConfigError(#[from] crate::config::Error),
|
ConfigError(#[from] crate::config::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
InternalError(#[from] InvalidMetadataValue),
|
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
|
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);
|
req.metadata_mut().insert("request-signature", signature);
|
||||||
Ok(req)
|
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