add support for multiple offers per node

This commit is contained in:
ghe0 2025-07-06 23:55:23 +03:00
parent f7df59e068
commit 0ef79e220c
Signed by: ghe0
GPG Key ID: 451028EE56A0FBB4
5 changed files with 75 additions and 46 deletions

2
Cargo.lock generated

@ -1184,7 +1184,7 @@ dependencies = [
[[package]]
name = "detee-shared"
version = "0.1.0"
source = "git+ssh://git@gitea.detee.cloud/testnet/proto.git?branch=credits_app#01e93d3a2e4502c0e8e72026e8a1c55810961815"
source = "git+ssh://git@gitea.detee.cloud/testnet/proto.git?branch=offers#4753a17fa29393b3f99b6dfcdcec48d935e6ebd9"
dependencies = [
"bincode",
"prost",

@ -37,7 +37,7 @@ detee-sgx = { git = "ssh://git@gitea.detee.cloud/testnet/detee-sgx.git", branch
shadow-rs = { version = "1.1.1", features = ["metadata"] }
serde_default_utils = "0.3.1"
detee-shared = { git = "ssh://git@gitea.detee.cloud/testnet/proto.git", branch = "credits_app" }
detee-shared = { git = "ssh://git@gitea.detee.cloud/testnet/proto.git", branch = "offers" }
# detee-shared = { path = "../detee-shared" }
[build-dependencies]

@ -138,16 +138,24 @@ impl Request {
}?;
let mut node_list_iter = node_list.iter();
let mut final_request = self.calculate_vm_request(
Config::get_detee_wallet()?,
node_list_iter.next().ok_or(Error::NoValidNodeFound)?,
);
let mut final_request: proto::NewVmReq = proto::NewVmReq { ..Default::default() };
while let Some(node) = node_list_iter.next() {
let new_vm_req = self.calculate_vm_request(Config::get_detee_wallet()?, node);
for offer in node.offers.iter() {
let new_vm_req = self.calculate_vm_request(
Config::get_detee_wallet()?,
&node.node_pubkey,
offer,
);
if new_vm_req.locked_nano < final_request.locked_nano {
final_request = new_vm_req;
}
}
}
if final_request.node_pubkey.is_empty() {
return Err(Error::NoValidNodeFound);
}
Ok(final_request)
}
@ -155,10 +163,11 @@ impl Request {
fn calculate_vm_request(
&self,
admin_pubkey: String,
node: &proto::VmNodeListResp,
node_pubkey: &str,
offer: &proto::VmNodeOffer,
) -> proto::NewVmReq {
let memory_per_cpu = node.memory_mib / node.vcpus;
let disk_per_cpu = node.disk_mib / node.vcpus;
let memory_per_cpu = offer.memory_mib / offer.vcpus;
let disk_per_cpu = offer.disk_mib / offer.vcpus;
let mut vcpus = self.vcpus;
if vcpus < (self.memory_gib * 1024).div_ceil(memory_per_cpu as u32) {
vcpus = (self.memory_gib * 1024).div_ceil(memory_per_cpu as u32);
@ -190,14 +199,14 @@ impl Request {
disk_size_mib,
public_ipv4,
self.hours,
node.price,
offer.price,
);
let brain_req = proto::NewVmReq {
uuid: String::new(),
hostname: self.hostname.clone(),
admin_pubkey,
node_pubkey: node.node_pubkey.clone(),
node_pubkey: node_pubkey.to_string(),
extra_ports,
public_ipv4,
public_ipv6: self.public_ipv6,
@ -208,13 +217,13 @@ impl Request {
kernel_sha,
dtrfs_url,
dtrfs_sha,
price_per_unit: node.price,
price_per_unit: offer.price,
locked_nano: nanocredits,
};
info!(
"Node {} can offer the VM at {} nanocredits for {} hours. Spec: {} vCPUs, {} MiB mem, {} MiB disk.",
node.ip, brain_req.locked_nano, self.hours, brain_req.vcpus, brain_req.memory_mib, brain_req.disk_size_mib
node_pubkey, brain_req.locked_nano, self.hours, brain_req.vcpus, brain_req.memory_mib, brain_req.disk_size_mib
);
brain_req

@ -88,7 +88,15 @@ impl crate::HumanOutput for VmNodeListResp {
"This node is located in the city {}, within the region of {}, in {}",
self.city, self.region, self.country
);
println!("The price multiplier for the node is {}.", self.price);
if self.offers.len() > 0 {
println!("The node is offering the following offers:");
}
for offer in self.offers.iter() {
println!(
" - {} vcpus, {} MiB of memory, {} MiB of storage at a price per unit of {}",
offer.vcpus, offer.memory_mib, offer.disk_mib, offer.price
);
}
}
}

@ -248,17 +248,27 @@ pub struct TabledVmNode {
impl From<proto::VmNodeListResp> for TabledVmNode {
fn from(brain_node: proto::VmNodeListResp) -> Self {
let (mut vcpus, mut memory_mib, mut disk_mib): (u64, u64, u64) = (0, 0, 0);
let mut price = 0;
for offer in brain_node.offers.iter() {
vcpus = vcpus.saturating_add(offer.vcpus);
memory_mib = memory_mib.saturating_add(offer.memory_mib);
disk_mib = disk_mib.saturating_add(offer.disk_mib);
if offer.price > price {
price = offer.price;
}
}
Self {
operator: brain_node.operator,
location: brain_node.city + ", " + &brain_node.region + ", " + &brain_node.country,
main_ip: brain_node.ip,
price: format!("{} nano/min", brain_node.price),
price: format!("{} nano/min", price),
reports: brain_node.reports.len(),
vcpus: brain_node.vcpus,
memory_mib: brain_node.memory_mib,
disk_mib: brain_node.disk_mib,
public_ipv4: brain_node.public_ipv4,
public_ipv6: brain_node.public_ipv6,
vcpus,
memory_mib,
disk_mib,
}
}
}
@ -426,16 +436,17 @@ pub fn print_node_offers(location: Location) -> Result<Vec<NodeOffer>, Error> {
let node_list = block_on(grpc::get_node_list(req))?;
let mut offers: Vec<NodeOffer> = Vec::new();
for node in node_list.iter() {
let mem_per_cpu = node.memory_mib / node.vcpus;
let disk_per_cpu = node.disk_mib / node.vcpus;
for i in 1..node.vcpus {
for offer in node.offers.iter() {
let mem_per_cpu = offer.memory_mib / offer.vcpus;
let disk_per_cpu = offer.disk_mib / offer.vcpus;
for i in 1..offer.vcpus {
let price_per_month = calculate_nanocredits(
(node.vcpus * i) as u32,
(offer.vcpus * i) as u32,
(mem_per_cpu * i) as u32,
(disk_per_cpu * i) as u32,
false,
732,
node.price,
offer.price,
) as f64
/ 1_000_000_000_f64;
let price_per_hour = price_per_month / 732_f64;
@ -453,6 +464,7 @@ pub fn print_node_offers(location: Location) -> Result<Vec<NodeOffer>, Error> {
});
}
}
}
offers.sort_by_key(|n| n.cost_m as u64);
Ok(offers)
}