pub mod app;
pub mod benchmark;
pub mod benchmark_cache;
pub mod cloud;
pub mod config;
pub mod error;
pub mod handlers;
pub mod pow;
pub mod pricing;
pub mod service;
pub mod signer;
pub mod types;
pub mod utils;
pub mod pricing_engine {
include!(concat!(env!("OUT_DIR"), "/pricing_engine.rs"));
}
#[cfg(test)]
pub mod tests;
pub use app::{
cleanup, init_operator_signer, load_operator_config, spawn_event_processor,
start_blockchain_listener, wait_for_shutdown,
};
pub use benchmark::cpu::CpuBenchmarkResult;
pub use benchmark::{BenchmarkProfile, BenchmarkRunConfig, run_benchmark, run_benchmark_suite};
pub use benchmark_cache::BenchmarkCache;
pub use benchmark_cache::BlueprintId;
pub use cloud::faas::{FaasPricing, FaasPricingFetcher};
pub use cloud::vm::{InstanceInfo, PricingFetcher};
pub use config::{OperatorConfig, load_config_from_path};
pub use error::{PricingError, Result};
pub use handlers::handle_blueprint_update;
pub use pow::{DEFAULT_POW_DIFFICULTY, generate_challenge, generate_proof, verify_proof};
pub use pricing::{
PriceModel, ResourcePricing, SubscriptionPricing, TeePricing, apply_tee_pricing,
calculate_price, load_job_pricing_from_toml, load_pricing_from_toml,
load_subscription_pricing_from_toml, load_tee_pricing_from_toml,
};
pub use service::blockchain::event::BlockchainEvent;
pub use service::rpc::server::{
JobPricingConfig, PricingEngineService, SubscriptionPricingConfig, run_rpc_server,
run_rpc_server_with_tee,
};
pub use signer::{
Confidentiality, OperatorId, OperatorSigner, SignableQuote, SignedJobQuote, SignedQuote,
};
use blueprint_core::info;
use std::collections::HashMap;
use std::path::Path;
use std::sync::Arc;
use tokio::sync::Mutex;
pub async fn init_benchmark_cache(config: &OperatorConfig) -> Result<Arc<BenchmarkCache>> {
let cache_path = format!("{}/benchmark_cache", config.database_path);
let cache = BenchmarkCache::new(cache_path)?;
info!("Benchmark cache initialized");
Ok(Arc::new(cache))
}
pub async fn init_pricing_config(
config_path: impl AsRef<Path>,
) -> Result<Arc<Mutex<HashMap<Option<u64>, Vec<ResourcePricing>>>>> {
let content = tokio::fs::read_to_string(config_path.as_ref())
.await
.map_err(|e| PricingError::Io(e))?;
let pricing_config = pricing::load_pricing_from_toml(&content)?;
info!(
"Pricing configuration loaded from {}",
config_path.as_ref().display()
);
Ok(Arc::new(Mutex::new(pricing_config)))
}
pub async fn init_job_pricing_config(
config_path: impl AsRef<Path>,
) -> Result<Arc<Mutex<service::rpc::server::JobPricingConfig>>> {
let content = tokio::fs::read_to_string(config_path.as_ref())
.await
.map_err(|e| PricingError::Io(e))?;
let job_config = pricing::load_job_pricing_from_toml(&content)?;
info!(
"Job pricing configuration loaded from {} ({} entries)",
config_path.as_ref().display(),
job_config.len()
);
Ok(Arc::new(Mutex::new(job_config)))
}
pub async fn init_tee_pricing_config(config_path: impl AsRef<Path>) -> Result<TeePricing> {
let content = tokio::fs::read_to_string(config_path.as_ref())
.await
.map_err(PricingError::Io)?;
let tee_config = pricing::load_tee_pricing_from_toml(&content)?;
if tee_config.available {
info!(
"TEE pricing loaded: provider={}, multiplier={}",
tee_config.provider, tee_config.multiplier
);
} else {
info!("TEE pricing: not available (no [tee] section or available=false)");
}
Ok(tee_config)
}
pub async fn init_subscription_pricing_config(
config_path: impl AsRef<Path>,
) -> Result<SubscriptionPricingConfig> {
let content = tokio::fs::read_to_string(config_path.as_ref())
.await
.map_err(PricingError::Io)?;
let config = pricing::load_subscription_pricing_from_toml(&content)?;
if config.is_empty() {
info!(
"No subscription pricing sections in {}; subscription/event requests will be rejected",
config_path.as_ref().display()
);
} else {
info!(
"Subscription pricing loaded from {} ({} entries)",
config_path.as_ref().display(),
config.len()
);
}
Ok(config)
}