switch from LP to credits

As part of open sourcing the software product, we should consider that
loyalty points are not the best language. Switching to "credits" makes
sense from a lot of points of view.

At the same time, this change allows an achitectural change towards
slots. Slots allow daemon resources to get booked based on the HW ratio
configured in the daemon config.
This commit is contained in:
ghe0 2025-06-24 01:45:07 +03:00
parent ee1b12f85f
commit 1ca66f3bc3
Signed by: ghe0
GPG Key ID: 451028EE56A0FBB4
11 changed files with 149 additions and 129 deletions

2
Cargo.lock generated

@ -1011,7 +1011,7 @@ dependencies = [
[[package]] [[package]]
name = "detee-shared" name = "detee-shared"
version = "0.1.0" version = "0.1.0"
source = "git+ssh://git@gitea.detee.cloud/testnet/proto?branch=surreal_brain_app#0b195b4589e4ec689af7ddca27dc051716ecee78" source = "git+ssh://git@gitea.detee.cloud/testnet/proto?branch=credits-v2#6d377926408953e8da2c0f4c6625d4fb90ba7652"
dependencies = [ dependencies = [
"bincode 2.0.1", "bincode 2.0.1",
"prost", "prost",

@ -15,7 +15,7 @@ serde_yaml = "0.9.34"
surrealdb = "2.2.2" surrealdb = "2.2.2"
tokio = { version = "1.44.2", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.44.2", features = ["macros", "rt-multi-thread"] }
tonic = { version = "0.12", features = ["tls"] } tonic = { version = "0.12", features = ["tls"] }
detee-shared = { git = "ssh://git@gitea.detee.cloud/testnet/proto", branch = "surreal_brain_app" } detee-shared = { git = "ssh://git@gitea.detee.cloud/testnet/proto", branch = "credits-v2" }
ed25519-dalek = "2.1.1" ed25519-dalek = "2.1.1"
bs58 = "0.5.1" bs58 = "0.5.1"
tokio-stream = "0.1.17" tokio-stream = "0.1.17"

@ -26,9 +26,9 @@ pub struct VmNode {
pub region: String, pub region: String,
pub city: String, pub city: String,
pub ip: String, pub ip: String,
pub avail_mem_mb: u32, pub avail_mem_mib: u32,
pub avail_vcpus: u32, pub avail_vcpus: u32,
pub avail_storage_gbs: u32, pub avail_storage_mib: u32,
pub avail_ipv4: u32, pub avail_ipv4: u32,
pub avail_ipv6: u32, pub avail_ipv6: u32,
pub avail_ports: u32, pub avail_ports: u32,
@ -59,9 +59,9 @@ impl VmNode {
#[derive(Serialize)] #[derive(Serialize)]
pub struct VmNodeResources { pub struct VmNodeResources {
pub avail_mem_mb: u32, pub avail_mem_mib: u32,
pub avail_vcpus: u32, pub avail_vcpus: u32,
pub avail_storage_gbs: u32, pub avail_storage_mib: u32,
pub avail_ipv4: u32, pub avail_ipv4: u32,
pub avail_ipv6: u32, pub avail_ipv6: u32,
pub avail_ports: u32, pub avail_ports: u32,
@ -83,9 +83,9 @@ pub struct VmNodeWithReports {
pub region: String, pub region: String,
pub city: String, pub city: String,
pub ip: String, pub ip: String,
pub avail_mem_mb: u32, pub avail_mem_mib: u64,
pub avail_vcpus: u32, pub avail_vcpus: u64,
pub avail_storage_gbs: u32, pub avail_storage_mib: u64,
pub avail_ipv4: u32, pub avail_ipv4: u32,
pub avail_ipv6: u32, pub avail_ipv6: u32,
pub avail_ports: u32, pub avail_ports: u32,
@ -106,15 +106,15 @@ impl VmNodeWithReports {
avail_ipv4 >= {} && avail_ipv4 >= {} &&
avail_ipv6 >= {} && avail_ipv6 >= {} &&
avail_vcpus >= {} && avail_vcpus >= {} &&
avail_mem_mb >= {} && avail_mem_mib >= {} &&
avail_storage_gbs >= {}\n", avail_storage_mib >= {}\n",
filters.free_ports, filters.free_ports,
filters.free_ports, filters.free_ports,
filters.offers_ipv4 as u32, filters.offers_ipv4 as u32,
filters.offers_ipv6 as u32, filters.offers_ipv6 as u32,
filters.vcpus, filters.vcpus,
filters.memory_mb, filters.memory_mib,
filters.storage_gb filters.storage_mib
); );
if !filters.city.is_empty() { if !filters.city.is_empty() {
query += &format!("&& city = '{}' ", filters.city); query += &format!("&& city = '{}' ", filters.city);
@ -170,9 +170,9 @@ pub struct NewVmReq {
pub extra_ports: Vec<u32>, pub extra_ports: Vec<u32>,
pub public_ipv4: bool, pub public_ipv4: bool,
pub public_ipv6: bool, pub public_ipv6: bool,
pub disk_size_gb: u32, pub disk_size_mib: u32,
pub vcpus: u32, pub vcpus: u32,
pub memory_mb: u32, pub memory_mib: u32,
pub dtrfs_url: String, pub dtrfs_url: String,
pub dtrfs_sha: String, pub dtrfs_sha: String,
pub kernel_sha: String, pub kernel_sha: String,
@ -266,7 +266,7 @@ impl NewVmReq {
->$new_vm_req ->$new_vm_req
->$vm_node ->$vm_node
CONTENT {{ CONTENT {{
created_at: time::now(), hostname: $hostname, vcpus: {}, memory_mb: {}, disk_size_gb: {}, created_at: time::now(), hostname: $hostname, vcpus: {}, memory_mib: {}, disk_size_mib: {},
extra_ports: {:?}, public_ipv4: {}, public_ipv6: {}, extra_ports: {:?}, public_ipv4: {}, public_ipv6: {},
dtrfs_url: $dtrfs_url, dtrfs_sha: $dtrfs_sha, kernel_url: $kernel_url, kernel_sha: $kernel_sha, dtrfs_url: $dtrfs_url, dtrfs_sha: $dtrfs_sha, kernel_url: $kernel_url, kernel_sha: $kernel_sha,
price_per_unit: {}, locked_nano: {locked_nano}, error: '' price_per_unit: {}, locked_nano: {locked_nano}, error: ''
@ -274,8 +274,8 @@ impl NewVmReq {
COMMIT TRANSACTION;", COMMIT TRANSACTION;",
self.vcpus, self.vcpus,
self.memory_mb, self.memory_mib,
self.disk_size_gb, self.disk_size_mib,
self.extra_ports, self.extra_ports,
self.public_ipv4, self.public_ipv4,
self.public_ipv6, self.public_ipv6,
@ -404,9 +404,9 @@ pub struct ActiveVm {
pub mapped_ports: Vec<(u32, u32)>, pub mapped_ports: Vec<(u32, u32)>,
pub public_ipv4: String, pub public_ipv4: String,
pub public_ipv6: String, pub public_ipv6: String,
pub disk_size_gb: u32, pub disk_size_mib: u32,
pub vcpus: u32, pub vcpus: u32,
pub memory_mb: u32, pub memory_mib: u32,
pub dtrfs_sha: String, pub dtrfs_sha: String,
pub kernel_sha: String, pub kernel_sha: String,
pub created_at: Datetime, pub created_at: Datetime,
@ -422,8 +422,8 @@ impl ActiveVm {
// I tried, but this can be done better. // I tried, but this can be done better.
// Storage cost should also be based on tier // Storage cost should also be based on tier
(self.vcpus as u64 * 10) (self.vcpus as u64 * 10)
+ ((self.memory_mb + 256) as u64 / 200) + ((self.memory_mib + 256) as u64 / 200)
+ (self.disk_size_gb as u64 / 10) + (self.disk_size_mib as u64 / 10)
+ (!self.public_ipv4.is_empty() as u64 * 10) + (!self.public_ipv4.is_empty() as u64 * 10)
} }
@ -483,9 +483,9 @@ impl ActiveVm {
mapped_ports, mapped_ports,
public_ipv4, public_ipv4,
public_ipv6, public_ipv6,
disk_size_gb: new_vm_req.disk_size_gb, disk_size_mib: new_vm_req.disk_size_mib,
vcpus: new_vm_req.vcpus, vcpus: new_vm_req.vcpus,
memory_mb: new_vm_req.memory_mb, memory_mib: new_vm_req.memory_mib,
dtrfs_sha: new_vm_req.dtrfs_sha, dtrfs_sha: new_vm_req.dtrfs_sha,
kernel_sha: new_vm_req.kernel_sha, kernel_sha: new_vm_req.kernel_sha,
created_at: new_vm_req.created_at.clone(), created_at: new_vm_req.created_at.clone(),
@ -517,11 +517,11 @@ impl ActiveVm {
if update_vm_req.vcpus > 0 { if update_vm_req.vcpus > 0 {
active_vm.vcpus = update_vm_req.vcpus; active_vm.vcpus = update_vm_req.vcpus;
} }
if update_vm_req.memory_mb > 0 { if update_vm_req.memory_mib > 0 {
active_vm.memory_mb = update_vm_req.memory_mb; active_vm.memory_mib = update_vm_req.memory_mib;
} }
if update_vm_req.disk_size_gb > 0 { if update_vm_req.disk_size_mib > 0 {
active_vm.disk_size_gb = update_vm_req.disk_size_gb; active_vm.disk_size_mib = update_vm_req.disk_size_mib;
} }
if !update_vm_req.dtrfs_sha.is_empty() && !update_vm_req.kernel_sha.is_empty() { if !update_vm_req.dtrfs_sha.is_empty() && !update_vm_req.kernel_sha.is_empty() {
active_vm.dtrfs_sha = update_vm_req.dtrfs_sha; active_vm.dtrfs_sha = update_vm_req.dtrfs_sha;
@ -670,9 +670,9 @@ pub struct UpdateVmReq {
pub admin: RecordId, pub admin: RecordId,
#[serde(rename = "out")] #[serde(rename = "out")]
pub vm_node: RecordId, pub vm_node: RecordId,
pub disk_size_gb: u32, pub disk_size_mib: u32,
pub vcpus: u32, pub vcpus: u32,
pub memory_mb: u32, pub memory_mib: u32,
pub dtrfs_url: String, pub dtrfs_url: String,
pub dtrfs_sha: String, pub dtrfs_sha: String,
pub kernel_sha: String, pub kernel_sha: String,
@ -688,9 +688,9 @@ pub struct UpdateVmEvent {
pub admin: RecordId, pub admin: RecordId,
#[serde(rename = "out")] #[serde(rename = "out")]
pub vm_node: RecordId, pub vm_node: RecordId,
pub disk_size_gb: u32, pub disk_size_mib: u32,
pub vcpus: u32, pub vcpus: u32,
pub memory_mb: u32, pub memory_mib: u32,
pub dtrfs_url: String, pub dtrfs_url: String,
pub dtrfs_sha: String, pub dtrfs_sha: String,
pub kernel_sha: String, pub kernel_sha: String,
@ -704,9 +704,9 @@ impl From<UpdateVmReq> for UpdateVmEvent {
vm_id: RecordId::from((VM_UPDATE_EVENT, update_vm_req.id.key().to_string())), vm_id: RecordId::from((VM_UPDATE_EVENT, update_vm_req.id.key().to_string())),
admin: update_vm_req.admin, admin: update_vm_req.admin,
vm_node: update_vm_req.vm_node, vm_node: update_vm_req.vm_node,
disk_size_gb: update_vm_req.disk_size_gb, disk_size_mib: update_vm_req.disk_size_mib,
vcpus: update_vm_req.vcpus, vcpus: update_vm_req.vcpus,
memory_mb: update_vm_req.memory_mb, memory_mib: update_vm_req.memory_mib,
dtrfs_url: update_vm_req.dtrfs_url, dtrfs_url: update_vm_req.dtrfs_url,
dtrfs_sha: update_vm_req.dtrfs_sha, dtrfs_sha: update_vm_req.dtrfs_sha,
kernel_sha: update_vm_req.kernel_sha, kernel_sha: update_vm_req.kernel_sha,
@ -743,17 +743,25 @@ impl UpdateVmReq {
return Ok(None); return Ok(None);
} }
let contract = contract.unwrap(); let contract = contract.unwrap();
// this is needed cause TryFrom does not support await let mem_per_cpu = contract.memory_mib / contract.vcpus;
self.vm_node = contract.vm_node; self.vm_node = contract.vm_node;
if !((self.vcpus != 0 && contract.vcpus != self.vcpus) if !((self.vcpus != 0 && contract.vcpus != self.vcpus)
|| (self.memory_mb != 0 && contract.memory_mb != self.memory_mb) || (self.memory_mib != 0 && contract.memory_mib != self.memory_mib)
|| (!self.dtrfs_sha.is_empty() && contract.dtrfs_sha != self.dtrfs_sha) || (!self.dtrfs_sha.is_empty() && contract.dtrfs_sha != self.dtrfs_sha)
|| (self.disk_size_gb != 0 && contract.disk_size_gb != self.disk_size_gb)) || (self.disk_size_mib != 0 && contract.disk_size_mib != self.disk_size_mib))
{ {
return Ok(Some(false)); return Ok(Some(false));
} }
// Do not allow user to unbalance memory and CPU on the node
if self.vcpus == 0 {
self.vcpus = self.memory_mib / mem_per_cpu;
}
if self.memory_mib == 0 {
self.memory_mib = self.vcpus * mem_per_cpu;
}
let _: Vec<Self> = db.insert(UPDATE_VM_REQ).relation(self).await?; let _: Vec<Self> = db.insert(UPDATE_VM_REQ).relation(self).await?;
Ok(Some(true)) Ok(Some(true))
} }
@ -779,9 +787,9 @@ pub struct DeletedVm {
pub mapped_ports: Vec<(u32, u32)>, pub mapped_ports: Vec<(u32, u32)>,
pub public_ipv4: String, pub public_ipv4: String,
pub public_ipv6: String, pub public_ipv6: String,
pub disk_size_gb: u32, pub disk_size_mib: u32,
pub vcpus: u32, pub vcpus: u32,
pub memory_mb: u32, pub memory_mib: u32,
pub dtrfs_sha: String, pub dtrfs_sha: String,
pub kernel_sha: String, pub kernel_sha: String,
pub created_at: Datetime, pub created_at: Datetime,
@ -799,9 +807,9 @@ impl From<ActiveVm> for DeletedVm {
mapped_ports: active_vm.mapped_ports, mapped_ports: active_vm.mapped_ports,
public_ipv4: active_vm.public_ipv4, public_ipv4: active_vm.public_ipv4,
public_ipv6: active_vm.public_ipv6, public_ipv6: active_vm.public_ipv6,
disk_size_gb: active_vm.disk_size_gb, disk_size_mib: active_vm.disk_size_mib,
vcpus: active_vm.vcpus, vcpus: active_vm.vcpus,
memory_mb: active_vm.memory_mb, memory_mib: active_vm.memory_mib,
dtrfs_sha: active_vm.dtrfs_sha, dtrfs_sha: active_vm.dtrfs_sha,
kernel_sha: active_vm.kernel_sha, kernel_sha: active_vm.kernel_sha,
created_at: active_vm.created_at, created_at: active_vm.created_at,
@ -862,8 +870,8 @@ impl DeletedVm {
// I tried, but this can be done better. // I tried, but this can be done better.
// Storage cost should also be based on tier // Storage cost should also be based on tier
(self.vcpus as u64 * 10) (self.vcpus as u64 * 10)
+ ((self.memory_mb + 256) as u64 / 200) + ((self.memory_mib + 256) as u64 / 200)
+ (self.disk_size_gb as u64 / 10) + (self.disk_size_mib as u64 / 10)
+ (!self.public_ipv4.is_empty() as u64 * 10) + (!self.public_ipv4.is_empty() as u64 * 10)
} }
@ -884,9 +892,9 @@ pub struct ActiveVmWithNode {
pub mapped_ports: Vec<(u32, u32)>, pub mapped_ports: Vec<(u32, u32)>,
pub public_ipv4: String, pub public_ipv4: String,
pub public_ipv6: String, pub public_ipv6: String,
pub disk_size_gb: u32, pub disk_size_mib: u32,
pub vcpus: u32, pub vcpus: u32,
pub memory_mb: u32, pub memory_mib: u32,
pub dtrfs_sha: String, pub dtrfs_sha: String,
pub kernel_sha: String, pub kernel_sha: String,
pub created_at: Datetime, pub created_at: Datetime,
@ -905,9 +913,9 @@ impl From<ActiveVmWithNode> for ActiveVm {
mapped_ports: val.mapped_ports, mapped_ports: val.mapped_ports,
public_ipv4: val.public_ipv4, public_ipv4: val.public_ipv4,
public_ipv6: val.public_ipv6, public_ipv6: val.public_ipv6,
disk_size_gb: val.disk_size_gb, disk_size_mib: val.disk_size_mib,
vcpus: val.vcpus, vcpus: val.vcpus,
memory_mb: val.memory_mb, memory_mib: val.memory_mib,
dtrfs_sha: val.dtrfs_sha, dtrfs_sha: val.dtrfs_sha,
kernel_sha: val.kernel_sha, kernel_sha: val.kernel_sha,
created_at: val.created_at, created_at: val.created_at,
@ -974,8 +982,8 @@ impl ActiveVmWithNode {
// I tried, but this can be done better. // I tried, but this can be done better.
// Storage cost should also be based on tier // Storage cost should also be based on tier
(self.vcpus as u64 * 10) (self.vcpus as u64 * 10)
+ ((self.memory_mb + 256) as u64 / 200) + ((self.memory_mib + 256) as u64 / 200)
+ (self.disk_size_gb as u64 / 10) + (self.disk_size_mib as u64 / 1024 / 10)
+ (!self.public_ipv4.is_empty() as u64 * 10) + (!self.public_ipv4.is_empty() as u64 * 10)
} }
@ -1005,9 +1013,9 @@ impl From<&old_brain::BrainData> for Vec<VmNode> {
region: old_node.region.clone(), region: old_node.region.clone(),
city: old_node.city.clone(), city: old_node.city.clone(),
ip: old_node.ip.clone(), ip: old_node.ip.clone(),
avail_mem_mb: old_node.avail_mem_mb, avail_mem_mib: old_node.avail_mem_mb,
avail_vcpus: old_node.avail_vcpus, avail_vcpus: old_node.avail_vcpus,
avail_storage_gbs: old_node.avail_storage_gbs, avail_storage_mib: old_node.avail_storage_gbs,
avail_ipv4: old_node.avail_ipv4, avail_ipv4: old_node.avail_ipv4,
avail_ipv6: old_node.avail_ipv6, avail_ipv6: old_node.avail_ipv6,
avail_ports: old_node.avail_ports, avail_ports: old_node.avail_ports,
@ -1037,9 +1045,9 @@ impl From<&old_brain::BrainData> for Vec<ActiveVm> {
mapped_ports, mapped_ports,
public_ipv4: old_c.public_ipv4.clone(), public_ipv4: old_c.public_ipv4.clone(),
public_ipv6: old_c.public_ipv6.clone(), public_ipv6: old_c.public_ipv6.clone(),
disk_size_gb: old_c.disk_size_gb, disk_size_mib: old_c.disk_size_gb,
vcpus: old_c.vcpus, vcpus: old_c.vcpus,
memory_mb: old_c.memory_mb, memory_mib: old_c.memory_mb,
dtrfs_sha: old_c.dtrfs_sha.clone(), dtrfs_sha: old_c.dtrfs_sha.clone(),
kernel_sha: old_c.kernel_sha.clone(), kernel_sha: old_c.kernel_sha.clone(),
price_per_unit: old_c.price_per_unit, price_per_unit: old_c.price_per_unit,

@ -133,7 +133,7 @@ impl BrainGeneralCli for GeneralCliServer {
match db::kick_contract(&self.db, &req.operator_wallet, &req.contract_uuid, &req.reason) match db::kick_contract(&self.db, &req.operator_wallet, &req.contract_uuid, &req.reason)
.await .await
{ {
Ok(nano_lp) => Ok(Response::new(KickResp { nano_lp })), Ok(nano_credits) => Ok(Response::new(KickResp { nano_credits })),
Err(e) Err(e)
if matches!( if matches!(
e, e,

@ -36,9 +36,9 @@ impl From<NewVmReq> for db::NewVmReq {
extra_ports: new_vm_req.extra_ports, extra_ports: new_vm_req.extra_ports,
public_ipv4: new_vm_req.public_ipv4, public_ipv4: new_vm_req.public_ipv4,
public_ipv6: new_vm_req.public_ipv6, public_ipv6: new_vm_req.public_ipv6,
disk_size_gb: new_vm_req.disk_size_gb, disk_size_mib: new_vm_req.disk_size_mib,
vcpus: new_vm_req.vcpus, vcpus: new_vm_req.vcpus,
memory_mb: new_vm_req.memory_mb, memory_mib: new_vm_req.memory_mib,
kernel_url: new_vm_req.kernel_url, kernel_url: new_vm_req.kernel_url,
kernel_sha: new_vm_req.kernel_sha, kernel_sha: new_vm_req.kernel_sha,
dtrfs_url: new_vm_req.dtrfs_url, dtrfs_url: new_vm_req.dtrfs_url,
@ -61,9 +61,9 @@ impl From<db::NewVmReq> for NewVmReq {
extra_ports: new_vm_req.extra_ports, extra_ports: new_vm_req.extra_ports,
public_ipv4: new_vm_req.public_ipv4, public_ipv4: new_vm_req.public_ipv4,
public_ipv6: new_vm_req.public_ipv6, public_ipv6: new_vm_req.public_ipv6,
disk_size_gb: new_vm_req.disk_size_gb, disk_size_mib: new_vm_req.disk_size_mib,
vcpus: new_vm_req.vcpus, vcpus: new_vm_req.vcpus,
memory_mb: new_vm_req.memory_mb, memory_mib: new_vm_req.memory_mib,
kernel_url: new_vm_req.kernel_url, kernel_url: new_vm_req.kernel_url,
kernel_sha: new_vm_req.kernel_sha, kernel_sha: new_vm_req.kernel_sha,
dtrfs_url: new_vm_req.dtrfs_url, dtrfs_url: new_vm_req.dtrfs_url,
@ -104,9 +104,9 @@ impl From<UpdateVmReq> for db::UpdateVmReq {
admin: RecordId::from((ACCOUNT, new_vm_req.admin_pubkey)), admin: RecordId::from((ACCOUNT, new_vm_req.admin_pubkey)),
// vm_node gets modified later, and only if the db::UpdateVmReq is required // vm_node gets modified later, and only if the db::UpdateVmReq is required
vm_node: RecordId::from((VM_NODE, String::new())), vm_node: RecordId::from((VM_NODE, String::new())),
disk_size_gb: new_vm_req.disk_size_gb, disk_size_mib: new_vm_req.disk_size_mib,
vcpus: new_vm_req.vcpus, vcpus: new_vm_req.vcpus,
memory_mb: new_vm_req.memory_mb, memory_mib: new_vm_req.memory_mib,
kernel_url: new_vm_req.kernel_url, kernel_url: new_vm_req.kernel_url,
kernel_sha: new_vm_req.kernel_sha, kernel_sha: new_vm_req.kernel_sha,
dtrfs_url: new_vm_req.dtrfs_url, dtrfs_url: new_vm_req.dtrfs_url,
@ -124,9 +124,9 @@ impl From<db::UpdateVmReq> for UpdateVmReq {
// daemon does not care about VM hostname // daemon does not care about VM hostname
hostname: String::new(), hostname: String::new(),
admin_pubkey: update_vm_req.admin.key().to_string(), admin_pubkey: update_vm_req.admin.key().to_string(),
disk_size_gb: update_vm_req.disk_size_gb, disk_size_mib: update_vm_req.disk_size_mib,
vcpus: update_vm_req.vcpus, vcpus: update_vm_req.vcpus,
memory_mb: update_vm_req.memory_mb, memory_mib: update_vm_req.memory_mib,
kernel_url: update_vm_req.kernel_url, kernel_url: update_vm_req.kernel_url,
kernel_sha: update_vm_req.kernel_sha, kernel_sha: update_vm_req.kernel_sha,
dtrfs_url: update_vm_req.dtrfs_url, dtrfs_url: update_vm_req.dtrfs_url,
@ -176,9 +176,9 @@ impl From<db::ActiveVmWithNode> for VmContract {
"{}, {}, {}", "{}, {}, {}",
db_c.vm_node.city, db_c.vm_node.region, db_c.vm_node.country db_c.vm_node.city, db_c.vm_node.region, db_c.vm_node.country
), ),
memory_mb: db_c.memory_mb, memory_mb: db_c.memory_mib,
vcpus: db_c.vcpus, vcpus: db_c.vcpus,
disk_size_gb: db_c.disk_size_gb, disk_size_gb: db_c.disk_size_mib,
mapped_ports: db_c mapped_ports: db_c
.mapped_ports .mapped_ports
.iter() .iter()
@ -230,6 +230,11 @@ impl From<db::VmNodeWithReports> for VmNodeListResp {
ip: vm_node.ip, ip: vm_node.ip,
reports: vm_node.reports.iter().map(|n| n.reason.clone()).collect(), reports: vm_node.reports.iter().map(|n| n.reason.clone()).collect(),
price: vm_node.price, price: vm_node.price,
vcpus: vm_node.avail_vcpus,
memory_mib: vm_node.avail_mem_mib,
disk_mib: vm_node.avail_storage_mib,
public_ipv4: vm_node.avail_ipv4 > 0,
public_ipv6: vm_node.avail_ipv6 > 0,
} }
} }
} }
@ -252,9 +257,9 @@ impl From<db::AppNodeWithReports> for AppNodeListResp {
impl From<VmNodeResources> for db::VmNodeResources { impl From<VmNodeResources> for db::VmNodeResources {
fn from(res: VmNodeResources) -> Self { fn from(res: VmNodeResources) -> Self {
Self { Self {
avail_mem_mb: res.avail_memory_mb, avail_mem_mib: res.avail_memory_mib,
avail_vcpus: res.avail_vcpus, avail_vcpus: res.avail_vcpus,
avail_storage_gbs: res.avail_storage_gb, avail_storage_mib: res.avail_storage_mib,
avail_ipv4: res.avail_ipv4, avail_ipv4: res.avail_ipv4,
avail_ipv6: res.avail_ipv6, avail_ipv6: res.avail_ipv6,
avail_ports: res.avail_ports, avail_ports: res.avail_ports,

@ -51,9 +51,9 @@ impl BrainVmDaemon for VmDaemonServer {
city: req.city, city: req.city,
ip: req.main_ip, ip: req.main_ip,
price: req.price, price: req.price,
avail_mem_mb: 0, avail_mem_mib: 0,
avail_vcpus: 0, avail_vcpus: 0,
avail_storage_gbs: 0, avail_storage_mib: 0,
avail_ipv4: 0, avail_ipv4: 0,
avail_ipv6: 0, avail_ipv6: 0,
avail_ports: 0, avail_ports: 0,
@ -273,10 +273,17 @@ impl BrainVmCli for VmCliServer {
let db_req: db::UpdateVmReq = req.clone().into(); let db_req: db::UpdateVmReq = req.clone().into();
if let Some(redirect) = db::check_pubsub_node(&self.db, db_req.vm_node.clone()).await? { println!("The node is {}", db_req.vm_node);
log::info!("redirect: {redirect}");
return Err(redirect); // TODO: vm_node is not known at this point. It is populated by `request_hw_update`.
} // As such, the pubsub node cannot be checked at this stage. This code should be moved,
// however we are not working on the redirect mechanic at the moment
//
// if let Some(redirect) = db::check_pubsub_node(&self.db, db_req.vm_node.clone()).await? {
// log::info!("redirect: {redirect}");
// return Err(redirect);
// }
let id = db_req.id.key().to_string(); let id = db_req.id.key().to_string();
let mut hostname_changed = false; let mut hostname_changed = false;

@ -6,7 +6,7 @@ DEFINE FUNCTION OVERWRITE fn::vm_price_per_minute(
LET $vm = (select * from $vm_id)[0]; LET $vm = (select * from $vm_id)[0];
LET $ip_price = IF $vm.public_ipv4.len() > 0 { 10 } ELSE { 0 }; LET $ip_price = IF $vm.public_ipv4.len() > 0 { 10 } ELSE { 0 };
RETURN ( RETURN (
($vm.vcpus * 10) + (($vm.memory_mb + 256) / 200) + ($vm.disk_size_gb / 10) + $ip_price) ($vm.vcpus * 10) + (($vm.memory_mib + 256) / 200) + ($vm.disk_size_mib / 1024 / 10) + $ip_price)
* $vm.price_per_unit; * $vm.price_per_unit;
}; };

@ -13,9 +13,9 @@ DEFINE FIELD country ON TABLE vm_node TYPE string;
DEFINE FIELD region ON TABLE vm_node TYPE string; DEFINE FIELD region ON TABLE vm_node TYPE string;
DEFINE FIELD city ON TABLE vm_node TYPE string; DEFINE FIELD city ON TABLE vm_node TYPE string;
DEFINE FIELD ip ON TABLE vm_node TYPE string; DEFINE FIELD ip ON TABLE vm_node TYPE string;
DEFINE FIELD avail_mem_mb ON TABLE vm_node TYPE int; DEFINE FIELD avail_mem_mib ON TABLE vm_node TYPE int;
DEFINE FIELD avail_vcpus ON TABLE vm_node TYPE int; DEFINE FIELD avail_vcpus ON TABLE vm_node TYPE int;
DEFINE FIELD avail_storage_gbs ON TABLE vm_node TYPE int; DEFINE FIELD avail_storage_mib ON TABLE vm_node TYPE int;
DEFINE FIELD avail_ipv4 ON TABLE vm_node TYPE int; DEFINE FIELD avail_ipv4 ON TABLE vm_node TYPE int;
DEFINE FIELD avail_ipv6 ON TABLE vm_node TYPE int; DEFINE FIELD avail_ipv6 ON TABLE vm_node TYPE int;
DEFINE FIELD avail_ports ON TABLE vm_node TYPE int; DEFINE FIELD avail_ports ON TABLE vm_node TYPE int;
@ -29,9 +29,9 @@ DEFINE FIELD hostname ON TABLE new_vm_req TYPE string;
DEFINE FIELD extra_ports ON TABLE new_vm_req TYPE array<int>; DEFINE FIELD extra_ports ON TABLE new_vm_req TYPE array<int>;
DEFINE FIELD public_ipv4 ON TABLE new_vm_req TYPE bool; DEFINE FIELD public_ipv4 ON TABLE new_vm_req TYPE bool;
DEFINE FIELD public_ipv6 ON TABLE new_vm_req TYPE bool; DEFINE FIELD public_ipv6 ON TABLE new_vm_req TYPE bool;
DEFINE FIELD disk_size_gb ON TABLE new_vm_req TYPE int; DEFINE FIELD disk_size_mib ON TABLE new_vm_req TYPE int;
DEFINE FIELD vcpus ON TABLE new_vm_req TYPE int; DEFINE FIELD vcpus ON TABLE new_vm_req TYPE int;
DEFINE FIELD memory_mb ON TABLE new_vm_req TYPE int; DEFINE FIELD memory_mib ON TABLE new_vm_req TYPE int;
DEFINE FIELD dtrfs_sha ON TABLE new_vm_req TYPE string; DEFINE FIELD dtrfs_sha ON TABLE new_vm_req TYPE string;
DEFINE FIELD dtrfs_url ON TABLE new_vm_req TYPE string; DEFINE FIELD dtrfs_url ON TABLE new_vm_req TYPE string;
DEFINE FIELD kernel_sha ON TABLE new_vm_req TYPE string; DEFINE FIELD kernel_sha ON TABLE new_vm_req TYPE string;
@ -46,9 +46,9 @@ DEFINE FIELD hostname ON TABLE active_vm TYPE string;
DEFINE FIELD mapped_ports ON TABLE active_vm TYPE array<[int, int]>; DEFINE FIELD mapped_ports ON TABLE active_vm TYPE array<[int, int]>;
DEFINE FIELD public_ipv4 ON TABLE active_vm TYPE string; DEFINE FIELD public_ipv4 ON TABLE active_vm TYPE string;
DEFINE FIELD public_ipv6 ON TABLE active_vm TYPE string; DEFINE FIELD public_ipv6 ON TABLE active_vm TYPE string;
DEFINE FIELD disk_size_gb ON TABLE active_vm TYPE int; DEFINE FIELD disk_size_mib ON TABLE active_vm TYPE int;
DEFINE FIELD vcpus ON TABLE active_vm TYPE int; DEFINE FIELD vcpus ON TABLE active_vm TYPE int;
DEFINE FIELD memory_mb ON TABLE active_vm TYPE int; DEFINE FIELD memory_mib ON TABLE active_vm TYPE int;
DEFINE FIELD dtrfs_sha ON TABLE active_vm TYPE string; DEFINE FIELD dtrfs_sha ON TABLE active_vm TYPE string;
DEFINE FIELD kernel_sha ON TABLE active_vm TYPE string; DEFINE FIELD kernel_sha ON TABLE active_vm TYPE string;
DEFINE FIELD created_at ON TABLE active_vm TYPE datetime; DEFINE FIELD created_at ON TABLE active_vm TYPE datetime;
@ -58,8 +58,8 @@ DEFINE FIELD collected_at ON TABLE active_vm TYPE datetime;
DEFINE TABLE update_vm_req TYPE RELATION FROM account TO vm_node SCHEMAFULL; DEFINE TABLE update_vm_req TYPE RELATION FROM account TO vm_node SCHEMAFULL;
DEFINE FIELD vcpus ON TABLE update_vm_req TYPE int; DEFINE FIELD vcpus ON TABLE update_vm_req TYPE int;
DEFINE FIELD memory_mb ON TABLE update_vm_req TYPE int; DEFINE FIELD memory_mib ON TABLE update_vm_req TYPE int;
DEFINE FIELD disk_size_gb ON TABLE update_vm_req TYPE int; DEFINE FIELD disk_size_mib ON TABLE update_vm_req TYPE int;
DEFINE FIELD dtrfs_sha ON TABLE update_vm_req TYPE string; DEFINE FIELD dtrfs_sha ON TABLE update_vm_req TYPE string;
DEFINE FIELD dtrfs_url ON TABLE update_vm_req TYPE string; DEFINE FIELD dtrfs_url ON TABLE update_vm_req TYPE string;
DEFINE FIELD kernel_sha ON TABLE update_vm_req TYPE string; DEFINE FIELD kernel_sha ON TABLE update_vm_req TYPE string;
@ -72,9 +72,9 @@ DEFINE FIELD hostname ON TABLE deleted_vm TYPE string;
DEFINE FIELD mapped_ports ON TABLE deleted_vm TYPE array<[int, int]>; DEFINE FIELD mapped_ports ON TABLE deleted_vm TYPE array<[int, int]>;
DEFINE FIELD public_ipv4 ON TABLE deleted_vm TYPE string; DEFINE FIELD public_ipv4 ON TABLE deleted_vm TYPE string;
DEFINE FIELD public_ipv6 ON TABLE deleted_vm TYPE string; DEFINE FIELD public_ipv6 ON TABLE deleted_vm TYPE string;
DEFINE FIELD disk_size_gb ON TABLE deleted_vm TYPE int; DEFINE FIELD disk_size_mib ON TABLE deleted_vm TYPE int;
DEFINE FIELD vcpus ON TABLE deleted_vm TYPE int; DEFINE FIELD vcpus ON TABLE deleted_vm TYPE int;
DEFINE FIELD memory_mb ON TABLE deleted_vm TYPE int; DEFINE FIELD memory_mib ON TABLE deleted_vm TYPE int;
DEFINE FIELD dtrfs_sha ON TABLE deleted_vm TYPE string; DEFINE FIELD dtrfs_sha ON TABLE deleted_vm TYPE string;
DEFINE FIELD kernel_sha ON TABLE deleted_vm TYPE string; DEFINE FIELD kernel_sha ON TABLE deleted_vm TYPE string;
DEFINE FIELD created_at ON TABLE deleted_vm TYPE datetime; DEFINE FIELD created_at ON TABLE deleted_vm TYPE datetime;

@ -10,9 +10,8 @@ FOR $contract IN (select * from active_vm fetch out) {
} ELSE { } ELSE {
$amount_due $amount_due
}; };
LET $escrow_multiplier = IF $operator.escrow < 5_000_000_000_000 { 1 } ELSE { 5 };
IF $node_is_online { IF $node_is_online {
UPDATE $operator.id SET balance += $amount_paid * $escrow_multiplier; UPDATE $operator.id SET balance += $amount_paid;
UPDATE $contract.id SET UPDATE $contract.id SET
locked_nano -= $amount_paid, locked_nano -= $amount_paid,
collected_at = time::now(); collected_at = time::now();

@ -91,8 +91,8 @@ async fn test_vm_daemon_resource_msg() {
avail_ipv4: 2, avail_ipv4: 2,
avail_ipv6: 88, avail_ipv6: 88,
avail_vcpus: 4, avail_vcpus: 4,
avail_memory_mb: 8192, avail_memory_mib: 8192,
avail_storage_gb: 100, avail_storage_mib: 102400,
max_ports_per_vm: 5, max_ports_per_vm: 5,
}; };
@ -114,9 +114,9 @@ async fn test_vm_daemon_resource_msg() {
assert!(vm_node_opt.is_some()); assert!(vm_node_opt.is_some());
let db::VmNode { let db::VmNode {
avail_mem_mb, avail_mem_mib,
avail_vcpus, avail_vcpus,
avail_storage_gbs, avail_storage_mib,
avail_ports, avail_ports,
avail_ipv4, avail_ipv4,
avail_ipv6, avail_ipv6,
@ -124,9 +124,9 @@ async fn test_vm_daemon_resource_msg() {
.. ..
} = vm_node_opt.unwrap(); } = vm_node_opt.unwrap();
assert_eq!(avail_mem_mb, req_data.avail_memory_mb); assert_eq!(avail_mem_mib, req_data.avail_memory_mib);
assert_eq!(avail_vcpus, req_data.avail_vcpus); assert_eq!(avail_vcpus, req_data.avail_vcpus);
assert_eq!(avail_storage_gbs, req_data.avail_storage_gb); assert_eq!(avail_storage_mib, req_data.avail_storage_mib);
assert_eq!(avail_ports, req_data.avail_ports); assert_eq!(avail_ports, req_data.avail_ports);
assert_eq!(avail_ipv4, req_data.avail_ipv4); assert_eq!(avail_ipv4, req_data.avail_ipv4);
assert_eq!(avail_ipv6, req_data.avail_ipv6); assert_eq!(avail_ipv6, req_data.avail_ipv6);

@ -180,9 +180,9 @@ vm_nodes:
region: England region: England
city: London city: London
ip: 173.234.17.2 ip: 173.234.17.2
avail_mem_mb: 26000 avail_mem_mib: 26000
avail_vcpus: 28 avail_vcpus: 28
avail_storage_gbs: 680 avail_storage_mib: 680
avail_ipv4: 2 avail_ipv4: 2
avail_ipv6: 65516 avail_ipv6: 65516
avail_ports: 19999 avail_ports: 19999
@ -196,9 +196,9 @@ vm_nodes:
region: Île-de-France region: Île-de-France
city: Paris city: Paris
ip: 156.146.63.215 ip: 156.146.63.215
avail_mem_mb: 123000 avail_mem_mib: 123000
avail_vcpus: 46 avail_vcpus: 46
avail_storage_gbs: 440 avail_storage_mib: 440
avail_ipv4: 2 avail_ipv4: 2
avail_ipv6: 0 avail_ipv6: 0
avail_ports: 20000 avail_ports: 20000
@ -212,9 +212,9 @@ vm_nodes:
region: Quebec region: Quebec
city: Montréal city: Montréal
ip: 184.107.169.199 ip: 184.107.169.199
avail_mem_mb: 30000 avail_mem_mib: 30000
avail_vcpus: 31 avail_vcpus: 31
avail_storage_gbs: 700 avail_storage_mib: 700
avail_ipv4: 0 avail_ipv4: 0
avail_ipv6: 0 avail_ipv6: 0
avail_ports: 20000 avail_ports: 20000
@ -228,9 +228,9 @@ vm_nodes:
region: British Columbia region: British Columbia
city: Vancouver city: Vancouver
ip: 149.22.95.1 ip: 149.22.95.1
avail_mem_mb: 109000 avail_mem_mib: 109000
avail_vcpus: 45 avail_vcpus: 45
avail_storage_gbs: 400 avail_storage_mib: 400
avail_ipv4: 25 avail_ipv4: 25
avail_ipv6: 0 avail_ipv6: 0
avail_ports: 20000 avail_ports: 20000
@ -244,9 +244,9 @@ vm_nodes:
region: California region: California
city: San Jose city: San Jose
ip: 149.36.48.99 ip: 149.36.48.99
avail_mem_mb: 120000 avail_mem_mib: 120000
avail_vcpus: 41 avail_vcpus: 41
avail_storage_gbs: 390 avail_storage_mib: 390
avail_ipv4: 23 avail_ipv4: 23
avail_ipv6: 0 avail_ipv6: 0
avail_ports: 19999 avail_ports: 19999
@ -260,9 +260,9 @@ vm_nodes:
region: British Columbia region: British Columbia
city: Vancouver city: Vancouver
ip: 149.22.95.28 ip: 149.22.95.28
avail_mem_mb: 125000 avail_mem_mib: 125000
avail_vcpus: 46 avail_vcpus: 46
avail_storage_gbs: 400 avail_storage_mib: 400
avail_ipv4: 26 avail_ipv4: 26
avail_ipv6: 0 avail_ipv6: 0
avail_ports: 20000 avail_ports: 20000
@ -277,9 +277,9 @@ vm_nodes:
region: England region: England
city: London city: London
ip: 193.234.17.2 ip: 193.234.17.2
avail_mem_mb: 28000 avail_mem_mib: 28000
avail_vcpus: 24 avail_vcpus: 24
avail_storage_gbs: 1680 avail_storage_mib: 1680
avail_ipv4: 1 avail_ipv4: 1
avail_ipv6: 0 avail_ipv6: 0
avail_ports: 19999 avail_ports: 19999
@ -293,9 +293,9 @@ vm_nodes:
region: England region: England
city: London city: London
ip: 193.234.17.2 ip: 193.234.17.2
avail_mem_mb: 28000 avail_mem_mib: 28000
avail_vcpus: 24 avail_vcpus: 24
avail_storage_gbs: 1680 avail_storage_mib: 1680
avail_ipv4: 1 avail_ipv4: 1
avail_ipv6: 0 avail_ipv6: 0
avail_ports: 19999 avail_ports: 19999
@ -312,9 +312,9 @@ vm_contracts:
exposed_ports: [] exposed_ports: []
public_ipv4: 156.146.63.216 public_ipv4: 156.146.63.216
public_ipv6: "" public_ipv6: ""
disk_size_gb: 10 disk_size_mib: 10240
vcpus: 2 vcpus: 2
memory_mb: 3000 memory_mib: 3000
kernel_sha: 3ec4fc5aa5729f515967ec71be4a851622785c0080f7191b1b07717149840151 kernel_sha: 3ec4fc5aa5729f515967ec71be4a851622785c0080f7191b1b07717149840151
dtrfs_sha: 3f6b3e5740f249eedfb2f7248c521a551be8b2676f7fcb040f3f3bc840a5004b dtrfs_sha: 3f6b3e5740f249eedfb2f7248c521a551be8b2676f7fcb040f3f3bc840a5004b
created_at: 2025-02-28T23:19:41.769423466Z created_at: 2025-02-28T23:19:41.769423466Z
@ -329,9 +329,9 @@ vm_contracts:
exposed_ports: [] exposed_ports: []
public_ipv4: 173.234.136.154 public_ipv4: 173.234.136.154
public_ipv6: "" public_ipv6: ""
disk_size_gb: 10 disk_size_mib: 10240
vcpus: 2 vcpus: 2
memory_mb: 3000 memory_mib: 3000
kernel_sha: 3ec4fc5aa5729f515967ec71be4a851622785c0080f7191b1b07717149840151 kernel_sha: 3ec4fc5aa5729f515967ec71be4a851622785c0080f7191b1b07717149840151
dtrfs_sha: 3f6b3e5740f249eedfb2f7248c521a551be8b2676f7fcb040f3f3bc840a5004b dtrfs_sha: 3f6b3e5740f249eedfb2f7248c521a551be8b2676f7fcb040f3f3bc840a5004b
created_at: 2025-03-06T19:51:39.595163157Z created_at: 2025-03-06T19:51:39.595163157Z
@ -347,9 +347,9 @@ vm_contracts:
- 38288 - 38288
public_ipv4: "" public_ipv4: ""
public_ipv6: "" public_ipv6: ""
disk_size_gb: 10 disk_size_mib: 10240
vcpus: 1 vcpus: 1
memory_mb: 1000 memory_mib: 1000
kernel_sha: 14e225e4aaf84cc2e0b5f64206121186ddebc4b378b886da3b2f7515dfd41692 kernel_sha: 14e225e4aaf84cc2e0b5f64206121186ddebc4b378b886da3b2f7515dfd41692
dtrfs_sha: 03ce24dbbe917fdd4f6347e61036805ddbdded5044c272bab188ef9333093bee dtrfs_sha: 03ce24dbbe917fdd4f6347e61036805ddbdded5044c272bab188ef9333093bee
created_at: 2025-03-12T16:28:24.749161605Z created_at: 2025-03-12T16:28:24.749161605Z
@ -364,9 +364,9 @@ vm_contracts:
exposed_ports: [] exposed_ports: []
public_ipv4: 149.22.95.2 public_ipv4: 149.22.95.2
public_ipv6: "" public_ipv6: ""
disk_size_gb: 10 disk_size_mib: 10240
vcpus: 2 vcpus: 2
memory_mb: 3000 memory_mib: 3000
kernel_sha: 3a68709138bed09c16671949cf1f03acee95a08381ba84fc70fb586001fa6767 kernel_sha: 3a68709138bed09c16671949cf1f03acee95a08381ba84fc70fb586001fa6767
dtrfs_sha: 0bb93443f65c9f4379ed469f94794f5c1bf14d8905b0b2c56a125df4a9ebe83e dtrfs_sha: 0bb93443f65c9f4379ed469f94794f5c1bf14d8905b0b2c56a125df4a9ebe83e
created_at: 2025-03-20T14:40:25.557753393Z created_at: 2025-03-20T14:40:25.557753393Z
@ -381,9 +381,9 @@ vm_contracts:
exposed_ports: [] exposed_ports: []
public_ipv4: 156.146.63.217 public_ipv4: 156.146.63.217
public_ipv6: "" public_ipv6: ""
disk_size_gb: 10 disk_size_mib: 10240
vcpus: 2 vcpus: 2
memory_mb: 3000 memory_mib: 3000
kernel_sha: e49c8587287b21df7600c04326fd7393524453918c14d67f73757dc769a13542 kernel_sha: e49c8587287b21df7600c04326fd7393524453918c14d67f73757dc769a13542
dtrfs_sha: b5f408d00e2b93dc594fed3a7f2466a9878802ff1c7ae502247471cd06728a45 dtrfs_sha: b5f408d00e2b93dc594fed3a7f2466a9878802ff1c7ae502247471cd06728a45
created_at: 2025-04-07T22:57:57.646151746Z created_at: 2025-04-07T22:57:57.646151746Z
@ -398,9 +398,9 @@ vm_contracts:
exposed_ports: [] exposed_ports: []
public_ipv4: 149.22.95.2 public_ipv4: 149.22.95.2
public_ipv6: "" public_ipv6: ""
disk_size_gb: 30 disk_size_mib: 30
vcpus: 1 vcpus: 1
memory_mb: 1000 memory_mib: 1000
kernel_sha: e49c8587287b21df7600c04326fd7393524453918c14d67f73757dc769a13542 kernel_sha: e49c8587287b21df7600c04326fd7393524453918c14d67f73757dc769a13542
dtrfs_sha: b5f408d00e2b93dc594fed3a7f2466a9878802ff1c7ae502247471cd06728a45 dtrfs_sha: b5f408d00e2b93dc594fed3a7f2466a9878802ff1c7ae502247471cd06728a45
created_at: 2025-04-12T13:44:56.957037550Z created_at: 2025-04-12T13:44:56.957037550Z
@ -415,9 +415,9 @@ vm_contracts:
exposed_ports: [] exposed_ports: []
public_ipv4: 149.36.48.100 public_ipv4: 149.36.48.100
public_ipv6: "" public_ipv6: ""
disk_size_gb: 10 disk_size_mib: 10240
vcpus: 4 vcpus: 4
memory_mb: 4000 memory_mib: 4000
kernel_sha: e49c8587287b21df7600c04326fd7393524453918c14d67f73757dc769a13542 kernel_sha: e49c8587287b21df7600c04326fd7393524453918c14d67f73757dc769a13542
dtrfs_sha: b5f408d00e2b93dc594fed3a7f2466a9878802ff1c7ae502247471cd06728a45 dtrfs_sha: b5f408d00e2b93dc594fed3a7f2466a9878802ff1c7ae502247471cd06728a45
created_at: 2025-04-15T00:46:35.622165457Z created_at: 2025-04-15T00:46:35.622165457Z
@ -433,9 +433,9 @@ vm_contracts:
- 46393 - 46393
public_ipv4: "" public_ipv4: ""
public_ipv6: "" public_ipv6: ""
disk_size_gb: 10 disk_size_mib: 10240
vcpus: 1 vcpus: 1
memory_mb: 1000 memory_mib: 1000
kernel_sha: e765e56166ef321b53399b9638584d1279821dbe3d46191c1f66bbaa075e7919 kernel_sha: e765e56166ef321b53399b9638584d1279821dbe3d46191c1f66bbaa075e7919
dtrfs_sha: d207644ee60d54009b6ecdfb720e2ec251cde31774dd249fcc7435aca0377990 dtrfs_sha: d207644ee60d54009b6ecdfb720e2ec251cde31774dd249fcc7435aca0377990
created_at: 2025-04-16T20:37:57.176592933Z created_at: 2025-04-16T20:37:57.176592933Z
@ -452,9 +452,9 @@ vm_contracts:
- 46393 - 46393
public_ipv4: "" public_ipv4: ""
public_ipv6: "" public_ipv6: ""
disk_size_gb: 10 disk_size_mib: 10240
vcpus: 1 vcpus: 1
memory_mb: 1000 memory_mib: 1000
kernel_sha: e765e56166ef321b53399b9638584d1279821dbe3d46191c1f66bbaa075e7919 kernel_sha: e765e56166ef321b53399b9638584d1279821dbe3d46191c1f66bbaa075e7919
dtrfs_sha: d207644ee60d54009b6ecdfb720e2ec251cde31774dd249fcc7435aca0377990 dtrfs_sha: d207644ee60d54009b6ecdfb720e2ec251cde31774dd249fcc7435aca0377990
created_at: 2025-04-16T20:37:57.176592933Z created_at: 2025-04-16T20:37:57.176592933Z
@ -470,9 +470,9 @@ vm_contracts:
- 46393 - 46393
public_ipv4: "" public_ipv4: ""
public_ipv6: "" public_ipv6: ""
disk_size_gb: 10 disk_size_mib: 10240
vcpus: 1 vcpus: 1
memory_mb: 1000 memory_mib: 1000
kernel_sha: e765e56166ef321b53399b9638584d1279821dbe3d46191c1f66bbaa075e7919 kernel_sha: e765e56166ef321b53399b9638584d1279821dbe3d46191c1f66bbaa075e7919
dtrfs_sha: d207644ee60d54009b6ecdfb720e2ec251cde31774dd249fcc7435aca0377990 dtrfs_sha: d207644ee60d54009b6ecdfb720e2ec251cde31774dd249fcc7435aca0377990
created_at: 2025-04-16T20:37:57.176592933Z created_at: 2025-04-16T20:37:57.176592933Z
@ -480,6 +480,7 @@ vm_contracts:
price_per_unit: 20000 price_per_unit: 20000
locked_nano: 12730960000 locked_nano: 12730960000
collected_at: 2025-04-20T00:34:15.461240342Z collected_at: 2025-04-20T00:34:15.461240342Z
app_nodes: app_nodes:
- node_pubkey: BiqoPUEoAxYxMRXUmyofoS9H1TBQgQqvLJ6MbWh88AQg - node_pubkey: BiqoPUEoAxYxMRXUmyofoS9H1TBQgQqvLJ6MbWh88AQg
operator_wallet: 7V3rEuh6j8VuwMVB5PyGqWKLmjJ4fYSv6WtrTL51NZTB operator_wallet: 7V3rEuh6j8VuwMVB5PyGqWKLmjJ4fYSv6WtrTL51NZTB