diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e4bc345b..836d04ac6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ All notable changes to this project will be documented in this file. ### Changes +- Smartcontract + - Migrate read callers in the CLI, sentinel, client, controlplane admin, and Rust SDK topology helper to read interfaces from `Device::new_interfaces` instead of the legacy `interfaces` enum vec, and adopt the `Device::find_interface` signature that returns `&NewInterface`. The legacy `interfaces` slot is still written on-disk via the per-write V2 projection from #3667; this PR only migrates reads. The temporary `Device::find_interface_legacy` helper is retained for the smartcontract program processors, which migrate in a later issue. Activator is intentionally excluded — it is deprecated ([#3659](https://github.com/malbeclabs/doublezero/issues/3659)) - Activator - Delete the `activator/` crate from the workspace; onchain allocation (RFC-11) supersedes it. The deployed activator was frozen in Phase 1 ([#3608](https://github.com/malbeclabs/doublezero/pull/3608), [#3628](https://github.com/malbeclabs/doublezero/pull/3628)) and removed from e2e in Phase 2 ([#3609](https://github.com/malbeclabs/doublezero/pull/3609), [#3610](https://github.com/malbeclabs/doublezero/pull/3610), [#3611](https://github.com/malbeclabs/doublezero/pull/3611), [#3629](https://github.com/malbeclabs/doublezero/pull/3629)). The `*/activate`, `*/reject`, and `*/closeaccount` onchain instructions and their SDK command modules remain in place for older CLIs until the min-version gate ([#3612](https://github.com/malbeclabs/doublezero/issues/3612)) - Smartcontract diff --git a/client/doublezero/src/dzd_latency.rs b/client/doublezero/src/dzd_latency.rs index 0af16c83d..1bd033434 100644 --- a/client/doublezero/src/dzd_latency.rs +++ b/client/doublezero/src/dzd_latency.rs @@ -9,8 +9,7 @@ pub(crate) fn get_device_tunnel_endpoints(device: &Device) -> Vec { let mut endpoints = vec![device.public_ip]; // Add all UserTunnelEndpoint interfaces - for iface in &device.interfaces { - let iface = iface.into_current_version(); + for iface in &device.new_interfaces { if iface.user_tunnel_endpoint && iface.ip_net != Default::default() { endpoints.push(iface.ip_net.ip()); } diff --git a/controlplane/doublezero-admin/src/cli/migrate.rs b/controlplane/doublezero-admin/src/cli/migrate.rs index 17b6ed2f8..2af090f75 100644 --- a/controlplane/doublezero-admin/src/cli/migrate.rs +++ b/controlplane/doublezero-admin/src/cli/migrate.rs @@ -106,10 +106,9 @@ impl FlexAlgoMigrateCliCommand { let mut devices_needing_backfill: Vec = Vec::new(); for (device_pubkey, device) in &device_entries { - let needs_backfill = device.interfaces.iter().any(|iface| { - let current = iface.into_v3(); - current.loopback_type == LoopbackType::Vpnv4 - && !current + let needs_backfill = device.new_interfaces.iter().any(|iface| { + iface.loopback_type == LoopbackType::Vpnv4 + && !iface .flex_algo_node_segments .iter() .any(|s| s.topology == *topology_pubkey) diff --git a/crates/sentinel/src/dz_ledger_reader.rs b/crates/sentinel/src/dz_ledger_reader.rs index 238b7e5fa..a5199e5bc 100644 --- a/crates/sentinel/src/dz_ledger_reader.rs +++ b/crates/sentinel/src/dz_ledger_reader.rs @@ -286,10 +286,9 @@ pub fn fetch_device_infos( .copied() .unwrap_or((0.0, 0.0)); let user_tunnel_endpoints = device - .interfaces + .new_interfaces .iter() .filter_map(|iface| { - let iface = iface.into_current_version(); if iface.user_tunnel_endpoint && iface.ip_net != Default::default() { Some(iface.ip_net.ip()) } else { diff --git a/crates/sentinel/src/multicast_publisher.rs b/crates/sentinel/src/multicast_publisher.rs index 056254cdb..2684ee553 100644 --- a/crates/sentinel/src/multicast_publisher.rs +++ b/crates/sentinel/src/multicast_publisher.rs @@ -468,10 +468,9 @@ impl MulticastDzLedgerClient for RpcMulticastDzLedgerClient { continue; } let user_tunnel_endpoints = device - .interfaces + .new_interfaces .iter() .filter_map(|iface| { - let iface = iface.into_current_version(); if iface.user_tunnel_endpoint && iface.ip_net != Default::default() { Some(iface.ip_net.ip()) } else { diff --git a/smartcontract/cli/src/device/get.rs b/smartcontract/cli/src/device/get.rs index 8b9441ce3..2da7654be 100644 --- a/smartcontract/cli/src/device/get.rs +++ b/smartcontract/cli/src/device/get.rs @@ -6,7 +6,7 @@ use doublezero_sdk::{ contributor::get::GetContributorCommand, device::get::GetDeviceCommand, exchange::get::GetExchangeCommand, }, - GetLocationCommand, Interface, + GetLocationCommand, NewInterface, }; use serde::Serialize; use solana_sdk::pubkey::Pubkey; @@ -45,11 +45,8 @@ struct InterfaceDisplay { pub tunnel_endpoint: bool, } -impl From<&Interface> for InterfaceDisplay { - fn from(iface: &Interface) -> Self { - // Convert to current version to ensure all fields are populated, even if the stored version is older - let iface = iface.into_current_version(); - +impl From<&NewInterface> for InterfaceDisplay { + fn from(iface: &NewInterface) -> Self { Self { name: iface.name.clone(), status: iface.status.to_string(), @@ -145,16 +142,15 @@ impl GetDeviceCliCommand { public_ip: device.public_ip.to_string(), dz_prefixes: device.dz_prefixes.to_string(), cyoa_ips: device - .interfaces + .new_interfaces .iter() - .map(|iface| iface.into_current_version()) .filter(|iface| iface.user_tunnel_endpoint) .map(|iface| iface.ip_net.to_string()) .collect(), metrics_publisher: device.metrics_publisher_pk.to_string(), mgmt_vrf: device.mgmt_vrf, interfaces: device - .interfaces + .new_interfaces .iter() .map(InterfaceDisplay::from) .collect(), diff --git a/smartcontract/cli/src/device/interface/create.rs b/smartcontract/cli/src/device/interface/create.rs index e602db74a..008a33d2f 100644 --- a/smartcontract/cli/src/device/interface/create.rs +++ b/smartcontract/cli/src/device/interface/create.rs @@ -67,9 +67,9 @@ impl CreateDeviceInterfaceCliCommand { .map_err(|_| eyre::eyre!("Device with pubkey/code '{}' not found", self.device))?; device - .interfaces + .new_interfaces .iter() - .find(|i| i.into_current_version().name == self.name) + .find(|i| i.name == self.name) .map_or(Ok(()), |_| { Err(eyre::eyre!( "Interface with name '{}' already exists", @@ -101,8 +101,7 @@ impl CreateDeviceInterfaceCliCommand { if dev.contributor_pk != device.contributor_pk { continue; } - for iface in &dev.interfaces { - let iface = iface.into_current_version(); + for iface in &dev.new_interfaces { if iface.ip_net == *ip_net { eyre::bail!( "IP {} is already assigned to interface {} on device {}", @@ -209,7 +208,8 @@ mod tests { metrics_publisher_pk: Pubkey::default(), owner: device2_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Activated, name: "Loopback100".to_string(), interface_type: InterfaceType::Loopback, @@ -224,9 +224,9 @@ mod tests { ip_net: "185.189.47.80/32".parse().unwrap(), node_segment_idx: 0, user_tunnel_endpoint: false, - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, diff --git a/smartcontract/cli/src/device/interface/delete.rs b/smartcontract/cli/src/device/interface/delete.rs index 25e1e0aeb..2db6dcd8a 100644 --- a/smartcontract/cli/src/device/interface/delete.rs +++ b/smartcontract/cli/src/device/interface/delete.rs @@ -33,7 +33,7 @@ impl DeleteDeviceInterfaceCliCommand { .map_err(|_| eyre::eyre!("Device not found"))?; let (_, iface) = device - .find_interface_legacy(&self.name) + .find_interface(&self.name) .map_err(|err| eyre::eyre!(err))?; // if a physical interface is Activated, it's part of a link and shouldn't be deleted. @@ -93,8 +93,9 @@ mod tests { metrics_publisher_pk: Pubkey::default(), owner: Pubkey::default(), mgmt_vrf: "default".to_string(), - interfaces: vec![ - CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![ + (&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet0".to_string(), interface_type: InterfaceType::Physical, @@ -109,9 +110,10 @@ mod tests { ip_net: "10.0.0.1/24".parse().unwrap(), node_segment_idx: 12, user_tunnel_endpoint: true, - } - .to_interface(), - CurrentInterfaceVersion { + }) + .try_into() + .unwrap(), + (&CurrentInterfaceVersion { status: InterfaceStatus::Activated, name: "Loopback0".to_string(), interface_type: InterfaceType::Loopback, @@ -126,10 +128,10 @@ mod tests { ip_net: "10.0.1.1/24".parse().unwrap(), node_segment_idx: 13, user_tunnel_endpoint: false, - } - .to_interface(), + }) + .try_into() + .unwrap(), ], - new_interfaces: vec![], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, diff --git a/smartcontract/cli/src/device/interface/get.rs b/smartcontract/cli/src/device/interface/get.rs index b86a52d57..744745587 100644 --- a/smartcontract/cli/src/device/interface/get.rs +++ b/smartcontract/cli/src/device/interface/get.rs @@ -43,14 +43,13 @@ impl GetDeviceInterfaceCliCommand { })?; let interface = device - .interfaces + .new_interfaces .iter() - .map(|i| i.into_current_version()) .find(|i| i.name.to_lowercase() == self.name.to_lowercase()) .ok_or_else(|| eyre::eyre!("Interface '{}' not found", self.name))?; let display = InterfaceDisplay { - name: interface.name, + name: interface.name.clone(), status: interface.status.to_string(), loopback_type: interface.loopback_type.to_string(), interface_cyoa: interface.interface_cyoa.to_string(), @@ -121,7 +120,8 @@ mod tests { ), owner: device1_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Activated, name: "eth0".to_string(), interface_type: InterfaceType::Physical, @@ -136,9 +136,9 @@ mod tests { ip_net: "10.0.0.1/24".parse().unwrap(), node_segment_idx: 42, user_tunnel_endpoint: true, - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, diff --git a/smartcontract/cli/src/device/interface/list.rs b/smartcontract/cli/src/device/interface/list.rs index a882904a9..79f6cef99 100644 --- a/smartcontract/cli/src/device/interface/list.rs +++ b/smartcontract/cli/src/device/interface/list.rs @@ -3,7 +3,7 @@ use clap::Args; use doublezero_program_common::types::NetworkV4; use doublezero_sdk::{ commands::device::{get::GetDeviceCommand, list::ListDeviceCommand}, - CurrentInterfaceVersion, InterfaceType, + InterfaceType, NewInterface, }; use doublezero_serviceability::state::interface::{ InterfaceCYOA, InterfaceDIA, LoopbackType, RoutingMode, @@ -56,9 +56,9 @@ impl ListDeviceInterfaceCliCommand { .map_err(|_| eyre::eyre!("Device not found"))?; device - .interfaces + .new_interfaces .iter() - .map(|iface| build_display(&iface.into_current_version(), &device.code)) + .map(|iface| build_display(iface, &device.code)) .collect() } else { let devices = client.list_device(ListDeviceCommand {})?; @@ -67,9 +67,9 @@ impl ListDeviceInterfaceCliCommand { .iter() .flat_map(|(_, device)| { device - .interfaces + .new_interfaces .iter() - .map(|iface| build_display(&iface.into_current_version(), &device.code)) + .map(|iface| build_display(iface, &device.code)) }) .collect() }; @@ -90,7 +90,7 @@ impl ListDeviceInterfaceCliCommand { } } -fn build_display(iface: &CurrentInterfaceVersion, device_code: &str) -> DeviceInterfaceDisplay { +fn build_display(iface: &NewInterface, device_code: &str) -> DeviceInterfaceDisplay { DeviceInterfaceDisplay { device: device_code.to_string(), name: iface.name.clone(), @@ -147,8 +147,9 @@ mod tests { metrics_publisher_pk: Pubkey::default(), owner: Pubkey::from_str_const("1111111FVAiSujNZVgYSc27t6zUTWoKfAGxbRzzPB"), mgmt_vrf: "default".to_string(), - interfaces: vec![ - CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![ + (&CurrentInterfaceVersion { status: InterfaceStatus::Activated, name: "eth0".to_string(), interface_type: InterfaceType::Physical, @@ -164,9 +165,10 @@ mod tests { ip_net: "10.0.0.1/24".parse().unwrap(), node_segment_idx: 12, user_tunnel_endpoint: true, - } - .to_interface(), - CurrentInterfaceVersion { + }) + .try_into() + .unwrap(), + (&CurrentInterfaceVersion { status: InterfaceStatus::Activated, name: "lo0".to_string(), interface_type: InterfaceType::Loopback, @@ -182,10 +184,10 @@ mod tests { ip_net: "10.0.1.1/24".parse().unwrap(), node_segment_idx: 13, user_tunnel_endpoint: false, - } - .to_interface(), + }) + .try_into() + .unwrap(), ], - new_interfaces: vec![], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, diff --git a/smartcontract/cli/src/device/interface/update.rs b/smartcontract/cli/src/device/interface/update.rs index be6f32fbf..8f27112e4 100644 --- a/smartcontract/cli/src/device/interface/update.rs +++ b/smartcontract/cli/src/device/interface/update.rs @@ -78,7 +78,7 @@ impl UpdateDeviceInterfaceCliCommand { })?; let (_, interface) = device - .find_interface_legacy(&self.name) + .find_interface(&self.name) .map_err(|e| eyre::eyre!(e.to_string()))?; // Prevent setting a loopback type on physical interfaces @@ -139,17 +139,16 @@ impl UpdateDeviceInterfaceCliCommand { if dev.contributor_pk != device.contributor_pk { continue; } - for iface in &dev.interfaces { - let iface_v = iface.into_current_version(); + for iface in &dev.new_interfaces { // Skip the interface being updated - if *pk == device_pk && iface_v.name.eq_ignore_ascii_case(&self.name) { + if *pk == device_pk && iface.name.eq_ignore_ascii_case(&self.name) { continue; } - if iface_v.ip_net == *ip_net { + if iface.ip_net == *ip_net { eyre::bail!( "IP {} is already assigned to interface {} on device {}", ip_net, - iface_v.name, + iface.name, dev.code ); } @@ -226,8 +225,9 @@ mod tests { metrics_publisher_pk: Pubkey::default(), owner: Pubkey::default(), mgmt_vrf: "default".to_string(), - interfaces: vec![ - CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![ + (&CurrentInterfaceVersion { status: InterfaceStatus::Activated, name: "Ethernet0".to_string(), interface_type: InterfaceType::Physical, @@ -242,9 +242,10 @@ mod tests { ip_net: "10.0.0.1/24".parse().unwrap(), node_segment_idx: 0, user_tunnel_endpoint: true, - } - .to_interface(), - CurrentInterfaceVersion { + }) + .try_into() + .unwrap(), + (&CurrentInterfaceVersion { status: InterfaceStatus::Activated, name: "Loopback0".to_string(), interface_type: InterfaceType::Loopback, @@ -259,10 +260,10 @@ mod tests { ip_net: "10.0.1.1/24".parse().unwrap(), node_segment_idx: 0, user_tunnel_endpoint: false, - } - .to_interface(), + }) + .try_into() + .unwrap(), ], - new_interfaces: vec![], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -362,7 +363,8 @@ mod tests { metrics_publisher_pk: Pubkey::default(), owner: Pubkey::default(), mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Activated, name: "Loopback0".to_string(), interface_type: InterfaceType::Loopback, @@ -377,9 +379,9 @@ mod tests { ip_net: "10.0.0.1/32".parse().unwrap(), node_segment_idx: 0, user_tunnel_endpoint: false, - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -411,7 +413,8 @@ mod tests { metrics_publisher_pk: Pubkey::default(), owner: Pubkey::default(), mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Activated, name: "Loopback100".to_string(), interface_type: InterfaceType::Loopback, @@ -426,9 +429,9 @@ mod tests { ip_net: "185.189.47.80/32".parse().unwrap(), node_segment_idx: 0, user_tunnel_endpoint: false, - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -508,7 +511,8 @@ mod tests { metrics_publisher_pk: Pubkey::default(), owner: Pubkey::default(), mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Activated, name: "Ethernet0".to_string(), interface_type: InterfaceType::Physical, @@ -523,9 +527,9 @@ mod tests { ip_net: "10.0.0.1/24".parse().unwrap(), node_segment_idx: 0, user_tunnel_endpoint: true, - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, diff --git a/smartcontract/cli/src/device/list.rs b/smartcontract/cli/src/device/list.rs index 7558146dc..996754c19 100644 --- a/smartcontract/cli/src/device/list.rs +++ b/smartcontract/cli/src/device/list.rs @@ -226,9 +226,8 @@ impl ListDeviceCliCommand { status: device.status, dz_prefixes: device.dz_prefixes.clone(), cyoa_ips: device - .interfaces + .new_interfaces .iter() - .map(|iface| iface.into_current_version()) .filter(|iface| iface.user_tunnel_endpoint) .map(|iface| iface.ip_net.to_string()) .collect(), diff --git a/smartcontract/cli/src/link/accept.rs b/smartcontract/cli/src/link/accept.rs index ed62a6b3c..28d442468 100644 --- a/smartcontract/cli/src/link/accept.rs +++ b/smartcontract/cli/src/link/accept.rs @@ -47,9 +47,8 @@ impl AcceptLinkCliCommand { })?; let side_z_iface = device_z - .interfaces + .new_interfaces .iter() - .map(|i| i.into_current_version()) .find(|i| i.name.to_lowercase() == self.side_z_interface.to_lowercase()) .ok_or_else(|| { eyre!( @@ -144,14 +143,15 @@ mod tests { exchange_pk: Pubkey::default(), code: "dev01".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { name: "Ethernet1/1".to_string(), status: InterfaceStatus::Unlinked, interface_type: InterfaceType::Physical, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], device_type: DeviceType::Hybrid, public_ip: "127.0.0.1".parse().unwrap(), status: DeviceStatus::Activated, @@ -188,7 +188,8 @@ mod tests { index: 2, reference_count: 0, code: "dev02".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/2".to_string(), interface_type: InterfaceType::Physical, @@ -198,9 +199,9 @@ mod tests { node_segment_idx: 0, user_tunnel_endpoint: false, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], location_pk: Pubkey::default(), exchange_pk: Pubkey::default(), device_type: doublezero_sdk::DeviceType::Hybrid, diff --git a/smartcontract/cli/src/link/dzx_create.rs b/smartcontract/cli/src/link/dzx_create.rs index 04629eed5..8c4aef165 100644 --- a/smartcontract/cli/src/link/dzx_create.rs +++ b/smartcontract/cli/src/link/dzx_create.rs @@ -92,9 +92,8 @@ impl CreateDZXLinkCliCommand { .map_err(|_| eyre::eyre!("Device not found"))?; let side_a_iface = side_a_dev - .interfaces + .new_interfaces .iter() - .map(|i| i.into_current_version()) .find(|i| i.name.to_lowercase() == self.side_a_interface.to_lowercase()) .ok_or_else(|| { eyre!( @@ -225,7 +224,8 @@ mod tests { status: DeviceStatus::Activated, owner: pda_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/1".to_string(), interface_type: InterfaceType::Physical, @@ -236,9 +236,9 @@ mod tests { user_tunnel_endpoint: true, mtu: 9000, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -271,7 +271,8 @@ mod tests { status: DeviceStatus::Activated, owner: pda_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/2".to_string(), interface_type: InterfaceType::Physical, @@ -282,9 +283,9 @@ mod tests { user_tunnel_endpoint: true, mtu: 9000, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -317,7 +318,8 @@ mod tests { status: DeviceStatus::Activated, owner: pda_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/3".to_string(), interface_type: InterfaceType::Physical, @@ -328,9 +330,9 @@ mod tests { user_tunnel_endpoint: true, mtu: 9000, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -496,7 +498,8 @@ mod tests { status: DeviceStatus::Activated, owner: pda_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/1".to_string(), interface_type: InterfaceType::Physical, @@ -507,9 +510,9 @@ mod tests { user_tunnel_endpoint: true, interface_cyoa: InterfaceCYOA::GREOverDIA, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -598,7 +601,8 @@ mod tests { status: DeviceStatus::Activated, owner: pda_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/1".to_string(), interface_type: InterfaceType::Physical, @@ -609,9 +613,9 @@ mod tests { node_segment_idx: 0, user_tunnel_endpoint: true, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, diff --git a/smartcontract/cli/src/link/wan_create.rs b/smartcontract/cli/src/link/wan_create.rs index e6c32129b..63bd665eb 100644 --- a/smartcontract/cli/src/link/wan_create.rs +++ b/smartcontract/cli/src/link/wan_create.rs @@ -95,9 +95,8 @@ impl CreateWANLinkCliCommand { .map_err(|_| eyre::eyre!("Device not found"))?; let side_a_iface = side_a_dev - .interfaces + .new_interfaces .iter() - .map(|i| i.into_current_version()) .find(|i| i.name.to_lowercase() == self.side_a_interface.to_lowercase()) .ok_or_else(|| { eyre!( @@ -137,9 +136,8 @@ impl CreateWANLinkCliCommand { } let side_z_iface = side_z_dev - .interfaces + .new_interfaces .iter() - .map(|i| i.into_current_version()) .find(|i| i.name.to_lowercase() == self.side_z_interface.to_lowercase()) .ok_or_else(|| { eyre!( @@ -272,7 +270,8 @@ mod tests { status: DeviceStatus::Activated, owner: pda_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/1".to_string(), interface_type: InterfaceType::Physical, @@ -283,9 +282,9 @@ mod tests { user_tunnel_endpoint: true, mtu: 9000, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -318,7 +317,8 @@ mod tests { status: DeviceStatus::Activated, owner: pda_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/2".to_string(), interface_type: InterfaceType::Physical, @@ -329,9 +329,9 @@ mod tests { user_tunnel_endpoint: true, mtu: 9000, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -364,7 +364,8 @@ mod tests { status: DeviceStatus::Activated, owner: pda_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/3".to_string(), interface_type: InterfaceType::Physical, @@ -375,9 +376,9 @@ mod tests { user_tunnel_endpoint: true, mtu: 9000, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -545,7 +546,8 @@ mod tests { status: DeviceStatus::Activated, owner: pda_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/1".to_string(), interface_type: InterfaceType::Physical, @@ -556,9 +558,9 @@ mod tests { user_tunnel_endpoint: true, interface_cyoa: InterfaceCYOA::GREOverDIA, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -591,7 +593,8 @@ mod tests { status: DeviceStatus::Activated, owner: pda_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/2".to_string(), interface_type: InterfaceType::Physical, @@ -601,9 +604,9 @@ mod tests { node_segment_idx: 0, user_tunnel_endpoint: true, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -683,7 +686,8 @@ mod tests { status: DeviceStatus::Activated, owner: pda_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/1".to_string(), interface_type: InterfaceType::Physical, @@ -694,9 +698,9 @@ mod tests { node_segment_idx: 0, user_tunnel_endpoint: true, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, @@ -727,7 +731,8 @@ mod tests { status: DeviceStatus::Activated, owner: pda_pubkey, mgmt_vrf: "default".to_string(), - interfaces: vec![CurrentInterfaceVersion { + interfaces: vec![], + new_interfaces: vec![(&CurrentInterfaceVersion { status: InterfaceStatus::Unlinked, name: "Ethernet1/2".to_string(), interface_type: InterfaceType::Physical, @@ -738,9 +743,9 @@ mod tests { node_segment_idx: 0, user_tunnel_endpoint: true, ..Default::default() - } - .to_interface()], - new_interfaces: vec![], + }) + .try_into() + .unwrap()], max_users: 255, users_count: 0, device_health: doublezero_serviceability::state::device::DeviceHealth::ReadyForUsers, diff --git a/smartcontract/cli/src/poll_for_activation.rs b/smartcontract/cli/src/poll_for_activation.rs index 005e39fa4..01dea5966 100644 --- a/smartcontract/cli/src/poll_for_activation.rs +++ b/smartcontract/cli/src/poll_for_activation.rs @@ -3,8 +3,8 @@ use doublezero_sdk::{ device::get::GetDeviceCommand, link::get::GetLinkCommand, multicastgroup::get::GetMulticastGroupCommand, user::get::GetUserCommand, }, - CurrentInterfaceVersion, Device, DeviceStatus, InterfaceStatus, Link, LinkStatus, - MulticastGroup, MulticastGroupStatus, User, UserStatus, + Device, DeviceStatus, Link, LinkStatus, MulticastGroup, MulticastGroupStatus, NewInterface, + User, UserStatus, }; use solana_sdk::pubkey::Pubkey; @@ -61,7 +61,7 @@ pub fn poll_for_device_interface_activated( client: &dyn CliCommand, device_pubkey: &Pubkey, interface_name: &str, -) -> eyre::Result { +) -> eyre::Result { let start_time = std::time::Instant::now(); let timeout = std::time::Duration::from_secs(20); let poll_interval = std::time::Duration::from_secs(1); @@ -82,20 +82,12 @@ pub fn poll_for_device_interface_activated( pubkey_or_code: device_pubkey.to_string(), }) { Ok((_, device)) => { - if let Some(iface) = device.interfaces.iter().find(|iface| { - iface.into_current_version().name.to_lowercase() - == interface_name.to_lowercase() - }) { - let current = iface.into_current_version(); - if current.status != InterfaceStatus::Pending { - return Ok(current); - } else { - last_error = Some(eyre::eyre!( - "Interface '{}' found but not activated (status: {:?})", - interface_name, - current.status - )); - } + if let Some(iface) = device + .new_interfaces + .iter() + .find(|iface| iface.name.to_lowercase() == interface_name.to_lowercase()) + { + return Ok(iface.clone()); } else { last_error = Some(eyre::eyre!( "Interface '{}' not found on device '{}'", diff --git a/smartcontract/cli/src/resource/verify.rs b/smartcontract/cli/src/resource/verify.rs index afe10721b..805e54fc2 100644 --- a/smartcontract/cli/src/resource/verify.rs +++ b/smartcontract/cli/src/resource/verify.rs @@ -903,8 +903,7 @@ fn verify_device_tunnel_block( // Check device loopback interfaces (only vpnv4/ipv4 loopback types) for (device_pk, device) in devices { - for interface in &device.interfaces { - let iface = interface.into_current_version(); + for iface in &device.new_interfaces { if iface.interface_type == InterfaceType::Loopback && (iface.loopback_type == LoopbackType::Vpnv4 || iface.loopback_type == LoopbackType::Ipv4) @@ -979,8 +978,7 @@ fn verify_segment_routing_ids( let mut in_use: HashMap = HashMap::new(); for (device_pk, device) in devices { - for interface in &device.interfaces { - let iface = interface.into_current_version(); + for iface in &device.new_interfaces { // Only check vpnv4/ipv4 loopbacks, and node_segment_idx == 0 means not allocated if iface.interface_type == InterfaceType::Loopback && (iface.loopback_type == LoopbackType::Vpnv4 diff --git a/smartcontract/sdk/rs/src/commands/topology/create.rs b/smartcontract/sdk/rs/src/commands/topology/create.rs index 1da0d9523..68c5fd58a 100644 --- a/smartcontract/sdk/rs/src/commands/topology/create.rs +++ b/smartcontract/sdk/rs/src/commands/topology/create.rs @@ -66,9 +66,9 @@ impl CreateTopologyCommand { .into_iter() .filter(|(_, device)| { device - .interfaces + .new_interfaces .iter() - .any(|i| i.into_current_version().loopback_type == LoopbackType::Vpnv4) + .any(|i| i.loopback_type == LoopbackType::Vpnv4) }) .map(|(pk, _)| pk) .collect(); @@ -105,7 +105,7 @@ mod tests { accountdata::AccountData, accounttype::AccountType, device::Device, - interface::{Interface, InterfaceV3, LoopbackType}, + interface::{LoopbackType, NewInterface}, topology::TopologyConstraint, }, }; @@ -173,19 +173,19 @@ mod tests { let vpnv4_device_pk = Pubkey::new_unique(); let vpnv4_device = Device { - interfaces: vec![Interface::V3(InterfaceV3 { + new_interfaces: vec![NewInterface { loopback_type: LoopbackType::Vpnv4, ..Default::default() - })], + }], ..Default::default() }; let other_device_pk = Pubkey::new_unique(); let other_device = Device { - interfaces: vec![Interface::V3(InterfaceV3 { + new_interfaces: vec![NewInterface { loopback_type: LoopbackType::None, ..Default::default() - })], + }], ..Default::default() }; diff --git a/smartcontract/sdk/rs/src/lib.rs b/smartcontract/sdk/rs/src/lib.rs index 5f9e21d07..2a5454dd7 100644 --- a/smartcontract/sdk/rs/src/lib.rs +++ b/smartcontract/sdk/rs/src/lib.rs @@ -22,6 +22,7 @@ pub use doublezero_serviceability::{ globalstate::GlobalState, interface::{ CurrentInterfaceVersion, Interface, InterfaceStatus, InterfaceType, LoopbackType, + NewInterface, }, link::{Link, LinkLinkType, LinkStatus}, location::{Location, LocationStatus},