From c4df839c179492a44fbfb58c9ba9c3a6371b8763 Mon Sep 17 00:00:00 2001 From: Greg Mitchell Date: Mon, 28 Jul 2025 15:13:15 +0000 Subject: [PATCH 1/2] activator: support for dzd metadata * Adds support for allocating IPs/segment IDs to interfaces. * Does not support reclaiming resources, this will be added in a later PR. --- activator/src/activator.rs | 25 +- activator/src/process/device.rs | 198 ++++++++++- activator/src/process/link.rs | 308 +++++++++++++++++- .../doublezero-record/src/instruction.rs | 2 +- smartcontract/sdk/rs/src/lib.rs | 5 +- 5 files changed, 515 insertions(+), 23 deletions(-) diff --git a/activator/src/activator.rs b/activator/src/activator.rs index c60df0e17..1afc5f3e4 100644 --- a/activator/src/activator.rs +++ b/activator/src/activator.rs @@ -18,8 +18,8 @@ use doublezero_sdk::{ link::list::ListLinkCommand, location::list::ListLocationCommand, user::list::ListUserCommand, }, - AccountData, DZClient, Device, DeviceStatus, Exchange, GetGlobalConfigCommand, LinkStatus, - Location, MulticastGroup, ProgramVersion, UserStatus, + AccountData, DZClient, Device, DeviceStatus, Exchange, GetGlobalConfigCommand, InterfaceType, + LinkStatus, Location, MulticastGroup, ProgramVersion, UserStatus, }; use log::{debug, error, info, warn}; use solana_sdk::pubkey::Pubkey; @@ -37,6 +37,7 @@ pub struct Activator { pub client: DZClient, pub link_ids: IDAllocator, + pub segment_routing_ids: IDAllocator, pub link_ips: IPBlockAllocator, pub multicastgroup_tunnel_ips: IPBlockAllocator, @@ -93,6 +94,7 @@ impl Activator { client, link_ips: IPBlockAllocator::new(config.device_tunnel_block.into()), link_ids: IDAllocator::new(0, vec![]), + segment_routing_ids: IDAllocator::new(1, vec![]), multicastgroup_tunnel_ips: IPBlockAllocator::new(config.multicastgroup_block.into()), user_tunnel_ips: IPBlockAllocator::new(config.user_tunnel_block.into()), devices: HashMap::new(), @@ -127,6 +129,14 @@ impl Activator { .iter() .filter(|(_, d)| d.status == DeviceStatus::Activated) { + device.interfaces.iter().for_each(|interface| { + if interface.node_segment_idx > 0 { + self.segment_routing_ids.assign(interface.node_segment_idx); + } + if interface.interface_type == InterfaceType::Loopback { + self.link_ips.assign_block(interface.ip_net.into()); + } + }); self.add_device(pubkey, device); } @@ -198,6 +208,7 @@ impl Activator { let multicastgroups = &mut self.multicastgroups; let solana_info = &self.solana_info; let state_transitions = &mut self.state_transitions; + let segment_routing_ids = &mut self.segment_routing_ids; self.client.gets_and_subscribe( move |client, pubkey, data| { @@ -205,7 +216,15 @@ impl Activator { match data { AccountData::Device(device) => { - process_device_event(client, pubkey, devices, device, state_transitions); + process_device_event( + client, + pubkey, + devices, + device, + state_transitions, + segment_routing_ids, + link_ips, + ); } AccountData::Link(tunnel) => { process_tunnel_event( diff --git a/activator/src/process/device.rs b/activator/src/process/device.rs index 00135b365..f83859812 100644 --- a/activator/src/process/device.rs +++ b/activator/src/process/device.rs @@ -1,8 +1,12 @@ +use crate::{idallocator::IDAllocator, ipblockallocator::IPBlockAllocator}; use doublezero_sdk::{ - commands::device::{activate::ActivateDeviceCommand, closeaccount::CloseAccountDeviceCommand}, - Device, DeviceStatus, DoubleZeroClient, + commands::device::{ + activate::ActivateDeviceCommand, closeaccount::CloseAccountDeviceCommand, + update::UpdateDeviceCommand, + }, + Device, DeviceStatus, DoubleZeroClient, InterfaceType, LoopbackType, NetworkV4, }; -use log::info; +use log::{error, info}; use solana_sdk::pubkey::Pubkey; use std::{ collections::{hash_map::Entry, HashMap}, @@ -17,6 +21,8 @@ pub fn process_device_event( devices: &mut DeviceMap, device: &Device, state_transitions: &mut HashMap<&'static str, usize>, + segment_routing_ids: &mut IDAllocator, + link_ips: &mut IPBlockAllocator, ) { match device.status { DeviceStatus::Pending => { @@ -84,6 +90,68 @@ pub fn process_device_event( } _ => {} } + + if device.status == DeviceStatus::Deleting || device.status == DeviceStatus::Rejected { + return; + } + + let mut do_update = false; + let mut interfaces = device.interfaces.clone(); + for interface in &mut interfaces { + if interface.interface_type == InterfaceType::Loopback { + if interface.node_segment_idx == 0 && interface.loopback_type == LoopbackType::Vpnv4 { + let id = segment_routing_ids.next_available(); + info!( + "Assigning segment routing ID {} to device {} interface {}", + id, device.code, interface.name + ); + interface.node_segment_idx = id; + do_update = true; + } + if interface.ip_net == NetworkV4::default() { + // Assign a loopback IP if not already set + interface.ip_net = link_ips + .next_available_block(1, 1) + .unwrap_or_else(|| { + error!( + "No available loopback IP block for device {} interface {}", + device.code, interface.name + ); + "0.0.0.0/0".parse().unwrap() + }) + .into(); + info!( + "Assigning IP {} to device {} interface {}", + interface.ip_net, device.code, interface.name + ); + do_update = true; + } + } + } + + if do_update { + info!("Updating device {}", device.code); + UpdateDeviceCommand { + pubkey: *pubkey, + code: None, + device_type: None, + public_ip: None, + dz_prefixes: None, + metrics_publisher: None, + contributor_pk: None, + bgp_asn: None, + dia_bgp_asn: None, + mgmt_vrf: None, + dns_servers: None, + ntp_servers: None, + interfaces: Some(interfaces), + } + .execute(client) + .map_err(|err| { + error!("Failed to update device {}: {}", device.code, err); + }) + .ok(); + } } #[cfg(test)] @@ -91,10 +159,15 @@ mod tests { use crate::tests::utils::{create_test_client, get_device_bump_seed}; use super::*; - use doublezero_sdk::{AccountData, AccountType, DeviceType}; + use doublezero_sdk::{ + AccountData, AccountType, DeviceType, Interface, CURRENT_INTERFACE_VERSION, + }; use doublezero_serviceability::{ instructions::DoubleZeroInstruction, - processors::device::{activate::DeviceActivateArgs, closeaccount::DeviceCloseAccountArgs}, + processors::device::{ + activate::DeviceActivateArgs, closeaccount::DeviceCloseAccountArgs, + update::DeviceUpdateArgs, + }, }; use mockall::{predicate, Sequence}; use solana_sdk::signature::Signature; @@ -105,6 +178,7 @@ mod tests { let mut seq = Sequence::new(); let mut devices = HashMap::new(); let mut client = create_test_client(); + let mut segment_ids = IDAllocator::new(1, vec![]); let device_pubkey = Pubkey::from_str_const("8KvLQiyKgrK3KyVGVVyT1Pmg7ahPVFsvHUVPg97oYynV"); let mut device = Device { @@ -127,9 +201,34 @@ mod tests { mgmt_vrf: "default".to_string(), dns_servers: vec![[8, 8, 8, 8].into(), [8, 8, 4, 4].into()], ntp_servers: vec![[192, 168, 1, 1].into(), [192, 168, 1, 2].into()], - interfaces: vec![], + interfaces: vec![ + Interface { + version: CURRENT_INTERFACE_VERSION, + name: "eth0".to_string(), + interface_type: InterfaceType::Physical, + loopback_type: LoopbackType::None, + vlan_id: 0, + ip_net: NetworkV4::default(), + node_segment_idx: 0, + user_tunnel_endpoint: false, + }, + Interface { + version: CURRENT_INTERFACE_VERSION, + name: "lo0".to_string(), + interface_type: InterfaceType::Loopback, + loopback_type: LoopbackType::Vpnv4, + vlan_id: 0, + ip_net: NetworkV4::default(), + node_segment_idx: 0, + user_tunnel_endpoint: false, + }, + ], }; + let mut expected_interfaces = device.interfaces.clone(); + expected_interfaces[1].ip_net = "1.1.1.1/32".parse().unwrap(); + expected_interfaces[1].node_segment_idx = 1; + let mut state_transitions: HashMap<&'static str, usize> = HashMap::new(); client @@ -142,12 +241,39 @@ mod tests { ) .returning(|_, _| Ok(Signature::new_unique())); + client + .expect_execute_transaction() + .times(1) + .in_sequence(&mut seq) + .with( + predicate::eq(DoubleZeroInstruction::UpdateDevice(DeviceUpdateArgs { + code: None, + device_type: None, + public_ip: None, + dz_prefixes: None, + metrics_publisher_pk: None, + contributor_pk: None, + bgp_asn: None, + dia_bgp_asn: None, + mgmt_vrf: None, + dns_servers: None, + ntp_servers: None, + interfaces: Some(expected_interfaces.clone()), + })), + predicate::always(), + ) + .returning(|_, _| Ok(Signature::new_unique())); + + let mut ip_block_allocator = IPBlockAllocator::new("1.1.1.0/24".parse().unwrap()); + process_device_event( &client, &device_pubkey, &mut devices, &device, &mut state_transitions, + &mut segment_ids, + &mut ip_block_allocator, ); assert!(devices.contains_key(&device_pubkey)); @@ -183,6 +309,8 @@ mod tests { &mut devices, &device, &mut state_transitions, + &mut segment_ids, + &mut ip_block_allocator, ); assert!(!devices.contains_key(&device_pubkey)); assert_eq!(state_transitions.len(), 2); @@ -193,8 +321,9 @@ mod tests { #[test] fn test_process_device_event_activated() { let mut devices = HashMap::new(); - let client = create_test_client(); + let mut client = create_test_client(); let pubkey = Pubkey::new_unique(); + let mut segment_ids = IDAllocator::new(1, vec![]); let mut device = Device { account_type: AccountType::Device, @@ -216,10 +345,58 @@ mod tests { mgmt_vrf: "default".to_string(), dns_servers: vec![[8, 8, 8, 8].into(), [8, 8, 4, 4].into()], ntp_servers: vec![[192, 168, 1, 1].into(), [192, 168, 1, 2].into()], - interfaces: vec![], + interfaces: vec![ + Interface { + version: CURRENT_INTERFACE_VERSION, + name: "eth0".to_string(), + interface_type: InterfaceType::Physical, + loopback_type: LoopbackType::None, + vlan_id: 0, + ip_net: NetworkV4::default(), + node_segment_idx: 0, + user_tunnel_endpoint: false, + }, + Interface { + version: CURRENT_INTERFACE_VERSION, + name: "lo0".to_string(), + interface_type: InterfaceType::Loopback, + loopback_type: LoopbackType::Vpnv4, + vlan_id: 0, + ip_net: NetworkV4::default(), + node_segment_idx: 0, + user_tunnel_endpoint: false, + }, + ], }; let mut state_transitions: HashMap<&'static str, usize> = HashMap::new(); + let mut ip_block_allocator = IPBlockAllocator::new("1.1.1.0/24".parse().unwrap()); + + let mut expected_interfaces = device.interfaces.clone(); + expected_interfaces[1].ip_net = "1.1.1.1/32".parse().unwrap(); + expected_interfaces[1].node_segment_idx = 1; + + client + .expect_execute_transaction() + .times(1) + .with( + predicate::eq(DoubleZeroInstruction::UpdateDevice(DeviceUpdateArgs { + code: None, + device_type: None, + public_ip: None, + dz_prefixes: None, + metrics_publisher_pk: None, + contributor_pk: None, + bgp_asn: None, + dia_bgp_asn: None, + mgmt_vrf: None, + dns_servers: None, + ntp_servers: None, + interfaces: Some(expected_interfaces.clone()), + })), + predicate::always(), + ) + .returning(|_, _| Ok(Signature::new_unique())); process_device_event( &client, @@ -227,18 +404,23 @@ mod tests { &mut devices, &device, &mut state_transitions, + &mut segment_ids, + &mut ip_block_allocator, ); assert!(devices.contains_key(&pubkey)); assert_eq!(devices.get(&pubkey).unwrap().device, device); device.dz_prefixes.push("10.0.1.1/24".parse().unwrap()); + device.interfaces = expected_interfaces; process_device_event( &client, &pubkey, &mut devices, &device, &mut state_transitions, + &mut segment_ids, + &mut ip_block_allocator, ); assert!(devices.contains_key(&pubkey)); diff --git a/activator/src/process/link.rs b/activator/src/process/link.rs index 0bbfdcafa..224dc5230 100644 --- a/activator/src/process/link.rs +++ b/activator/src/process/link.rs @@ -1,13 +1,17 @@ use crate::{idallocator::IDAllocator, ipblockallocator::IPBlockAllocator}; use doublezero_sdk::{ - commands::link::{ - activate::ActivateLinkCommand, closeaccount::CloseAccountLinkCommand, - reject::RejectLinkCommand, + commands::{ + device::{get::GetDeviceCommand, update::UpdateDeviceCommand}, + link::{ + activate::ActivateLinkCommand, closeaccount::CloseAccountLinkCommand, + reject::RejectLinkCommand, + }, }, DoubleZeroClient, Link, LinkStatus, }; +use ipnetwork::Ipv4Network; use log::info; -use solana_sdk::pubkey::Pubkey; +use solana_sdk::{pubkey::Pubkey, signature::Signature}; use std::{collections::HashMap, fmt::Write}; pub fn process_tunnel_event( @@ -46,6 +50,38 @@ pub fn process_tunnel_event( *state_transitions .entry("tunnel-pending-to-activated") .or_insert(0) += 1; + + // get the first and second ips in the network, but don't throw away + // the netmask/prefix. unwraps are safe below because we already have + // checked that we have a valid tunnel_net + let side_a_ip = + Ipv4Network::new(tunnel_net.nth(0).unwrap(), tunnel_net.prefix()) + .unwrap(); + let side_z_ip = + Ipv4Network::new(tunnel_net.nth(1).unwrap(), tunnel_net.prefix()) + .unwrap(); + + if let Err(e) = assign_ip_to_dev_interface( + client, + side_a_ip, + &link.side_a_pk, + &link.side_a_iface_name, + ) { + write!(&mut log_msg, " Error assigning side A IP: {e}").unwrap(); + } else { + write!(&mut log_msg, " Assigned side A IP: {side_a_ip}").unwrap(); + } + + if let Err(e) = assign_ip_to_dev_interface( + client, + side_z_ip, + &link.side_z_pk, + &link.side_z_iface_name, + ) { + write!(&mut log_msg, " Error assigning side Z IP: {e}").unwrap(); + } else { + write!(&mut log_msg, " Assigned side Z IP: {side_a_ip}").unwrap(); + } } Err(e) => write!(&mut log_msg, " Error {e}").unwrap(), } @@ -98,6 +134,28 @@ pub fn process_tunnel_event( *state_transitions .entry("tunnel-deleting-to-deactivated") .or_insert(0) += 1; + + let zero_ip = "0.0.0.0/0".parse().unwrap(); + + if let Err(e) = assign_ip_to_dev_interface( + client, + zero_ip, + &link.side_a_pk, + &link.side_a_iface_name, + ) { + write!(&mut log_msg, " Error assigning side A IP to {zero_ip}: {e}") + .unwrap(); + } + + if let Err(e) = assign_ip_to_dev_interface( + client, + zero_ip, + &link.side_z_pk, + &link.side_z_iface_name, + ) { + write!(&mut log_msg, " Error assigning side Z IP to {zero_ip}: {e}") + .unwrap(); + } } Err(e) => write!(&mut log_msg, " Error {e}").unwrap(), } @@ -106,21 +164,68 @@ pub fn process_tunnel_event( } } +fn assign_ip_to_dev_interface( + client: &dyn DoubleZeroClient, + ip_net: Ipv4Network, + dev: &Pubkey, + iface_name: &str, +) -> eyre::Result { + let (pubkey, device) = GetDeviceCommand { + pubkey_or_code: dev.to_string(), + } + .execute(client)?; + + let mut interfaces = device.interfaces.clone(); + if let Some(iface) = interfaces.iter_mut().find(|i| i.name == iface_name) { + iface.ip_net = ip_net.into(); + } else { + return Err(eyre::eyre!( + "Interface {} not found on device {}", + iface_name, + pubkey + )); + } + + UpdateDeviceCommand { + pubkey: *dev, + code: None, + device_type: None, + public_ip: None, + dz_prefixes: None, + metrics_publisher: None, + contributor_pk: None, + bgp_asn: None, + dia_bgp_asn: None, + mgmt_vrf: None, + dns_servers: None, + ntp_servers: None, + interfaces: Some(interfaces), + } + .execute(client) +} + #[cfg(test)] mod tests { use crate::{ idallocator::IDAllocator, ipblockallocator::IPBlockAllocator, process::link::process_tunnel_event, - tests::utils::{create_test_client, get_tunnel_bump_seed}, + tests::utils::{create_test_client, get_device_bump_seed, get_tunnel_bump_seed}, + }; + use doublezero_sdk::{ + AccountData, AccountType, Device, DeviceStatus, DeviceType, Interface, InterfaceType, Link, + LinkLinkType, LinkStatus, LoopbackType, NetworkV4, NetworkV4List, + CURRENT_INTERFACE_VERSION, }; - use doublezero_sdk::{AccountData, AccountType, Link, LinkLinkType, LinkStatus}; use doublezero_serviceability::{ instructions::DoubleZeroInstruction, - processors::link::{ - activate::LinkActivateArgs, closeaccount::LinkCloseAccountArgs, reject::LinkRejectArgs, + processors::{ + device::update::DeviceUpdateArgs, + link::{ + activate::LinkActivateArgs, closeaccount::LinkCloseAccountArgs, + reject::LinkRejectArgs, + }, }, - types::NetworkV4, }; use mockall::{predicate, Sequence}; use solana_sdk::{pubkey::Pubkey, signature::Signature}; @@ -155,6 +260,60 @@ mod tests { side_z_iface_name: "eth1".to_string(), }; + let device1 = Device { + account_type: AccountType::Device, + owner: tunnel.owner, + index: 0, + bump_seed: get_device_bump_seed(&client), + location_pk: Pubkey::new_unique(), + exchange_pk: Pubkey::new_unique(), + device_type: DeviceType::Switch, + public_ip: "1.2.3.4".parse().unwrap(), + status: DeviceStatus::Activated, + code: "Device1".to_string(), + dz_prefixes: NetworkV4List::default(), + metrics_publisher_pk: Pubkey::new_unique(), + contributor_pk: tunnel.contributor_pk, + bgp_asn: 65001, + dia_bgp_asn: 65002, + mgmt_vrf: "mgmt".to_string(), + dns_servers: vec![], + ntp_servers: vec![], + interfaces: vec![ + Interface { + version: CURRENT_INTERFACE_VERSION, + name: tunnel.side_a_iface_name.clone(), + interface_type: InterfaceType::Physical, + loopback_type: LoopbackType::None, + vlan_id: 0, + ip_net: NetworkV4::default(), + node_segment_idx: 0, + user_tunnel_endpoint: false, + }, + Interface { + version: CURRENT_INTERFACE_VERSION, + name: "lo0".to_string(), + interface_type: InterfaceType::Loopback, + loopback_type: LoopbackType::Vpnv4, + vlan_id: 0, + ip_net: NetworkV4::default(), + node_segment_idx: 0, + user_tunnel_endpoint: false, + }, + ], + reference_count: 0, + }; + + let mut device2 = device1.clone(); + device2.public_ip = "1.2.3.5".parse().unwrap(); + device2.code = "Device2".to_string(); + device2.interfaces[0].name = tunnel.side_z_iface_name.clone(); + + let mut expected_interfaces1 = device1.interfaces.clone(); + let mut expected_interfaces2 = device2.interfaces.clone(); + expected_interfaces1[0].ip_net = "10.0.0.0/31".parse().unwrap(); + expected_interfaces2[0].ip_net = "10.0.0.1/31".parse().unwrap(); + client .expect_execute_transaction() .times(1) @@ -168,6 +327,68 @@ mod tests { ) .returning(|_, _| Ok(Signature::new_unique())); + let dev1 = device1.clone(); + client + .expect_get() + .times(1) + .in_sequence(&mut seq) + .with(predicate::eq(tunnel.side_a_pk)) + .returning(move |_| Ok(AccountData::Device(dev1.clone()))); + + client + .expect_execute_transaction() + .times(1) + .in_sequence(&mut seq) + .with( + predicate::eq(DoubleZeroInstruction::UpdateDevice(DeviceUpdateArgs { + code: None, + device_type: None, + public_ip: None, + dz_prefixes: None, + metrics_publisher_pk: None, + contributor_pk: None, + bgp_asn: None, + dia_bgp_asn: None, + mgmt_vrf: None, + dns_servers: None, + ntp_servers: None, + interfaces: Some(expected_interfaces1.clone()), + })), + predicate::always(), + ) + .returning(|_, _| Ok(Signature::new_unique())); + + let dev2 = device2.clone(); + client + .expect_get() + .times(1) + .in_sequence(&mut seq) + .with(predicate::eq(tunnel.side_z_pk)) + .returning(move |_| Ok(AccountData::Device(dev2.clone()))); + + client + .expect_execute_transaction() + .times(1) + .in_sequence(&mut seq) + .with( + predicate::eq(DoubleZeroInstruction::UpdateDevice(DeviceUpdateArgs { + code: None, + device_type: None, + public_ip: None, + dz_prefixes: None, + metrics_publisher_pk: None, + contributor_pk: None, + bgp_asn: None, + dia_bgp_asn: None, + mgmt_vrf: None, + dns_servers: None, + ntp_servers: None, + interfaces: Some(expected_interfaces2.clone()), + })), + predicate::always(), + ) + .returning(|_, _| Ok(Signature::new_unique())); + let mut state_transitions: HashMap<&'static str, usize> = HashMap::new(); process_tunnel_event( @@ -190,7 +411,9 @@ mod tests { let tunnel2 = tunnel.clone(); client .expect_get() - .with(predicate::eq(tunnel_pubkey)) + .times(1) + .in_sequence(&mut seq) + .withf(move |pk| *pk == tunnel_pubkey) .returning(move |_| Ok(AccountData::Link(tunnel2.clone()))); client @@ -205,6 +428,71 @@ mod tests { ) .returning(|_, _| Ok(Signature::new_unique())); + expected_interfaces1[0].ip_net = "0.0.0.0/0".parse().unwrap(); + expected_interfaces2[0].ip_net = "0.0.0.0/0".parse().unwrap(); + + let dev1 = device1.clone(); + client + .expect_get() + .times(1) + .in_sequence(&mut seq) + .with(predicate::eq(tunnel.side_a_pk)) + .returning(move |_| Ok(AccountData::Device(dev1.clone()))); + + client + .expect_execute_transaction() + .times(1) + .in_sequence(&mut seq) + .with( + predicate::eq(DoubleZeroInstruction::UpdateDevice(DeviceUpdateArgs { + code: None, + device_type: None, + public_ip: None, + dz_prefixes: None, + metrics_publisher_pk: None, + contributor_pk: None, + bgp_asn: None, + dia_bgp_asn: None, + mgmt_vrf: None, + dns_servers: None, + ntp_servers: None, + interfaces: Some(expected_interfaces1.clone()), + })), + predicate::always(), + ) + .returning(|_, _| Ok(Signature::new_unique())); + + let dev2 = device2.clone(); + client + .expect_get() + .times(1) + .in_sequence(&mut seq) + .with(predicate::eq(tunnel.side_z_pk)) + .returning(move |_| Ok(AccountData::Device(dev2.clone()))); + + client + .expect_execute_transaction() + .times(1) + .in_sequence(&mut seq) + .with( + predicate::eq(DoubleZeroInstruction::UpdateDevice(DeviceUpdateArgs { + code: None, + device_type: None, + public_ip: None, + dz_prefixes: None, + metrics_publisher_pk: None, + contributor_pk: None, + bgp_asn: None, + dia_bgp_asn: None, + mgmt_vrf: None, + dns_servers: None, + ntp_servers: None, + interfaces: Some(expected_interfaces2.clone()), + })), + predicate::always(), + ) + .returning(|_, _| Ok(Signature::new_unique())); + let assigned_ips = link_ips.assigned_ips.clone(); process_tunnel_event( diff --git a/smartcontract/programs/doublezero-record/src/instruction.rs b/smartcontract/programs/doublezero-record/src/instruction.rs index 3e3b3468f..8e6a1195f 100644 --- a/smartcontract/programs/doublezero-record/src/instruction.rs +++ b/smartcontract/programs/doublezero-record/src/instruction.rs @@ -113,7 +113,7 @@ impl<'a> RecordInstruction<'a> { /// Packs a [`RecordInstruction`] into a byte buffer. pub fn pack(&self) -> Vec { - let mut buf = Vec::with_capacity(size_of::()); + let mut buf = Vec::with_capacity(std::mem::size_of::()); match self { Self::Initialize => buf.push(0), Self::Write { offset, data } => { diff --git a/smartcontract/sdk/rs/src/lib.rs b/smartcontract/sdk/rs/src/lib.rs index f30667748..8980a8b46 100644 --- a/smartcontract/sdk/rs/src/lib.rs +++ b/smartcontract/sdk/rs/src/lib.rs @@ -13,7 +13,10 @@ pub use doublezero_serviceability::{ accountdata::AccountData, accounttype::AccountType, contributor::{Contributor, ContributorStatus}, - device::{Device, DeviceStatus, DeviceType, CURRENT_INTERFACE_VERSION}, + device::{ + Device, DeviceStatus, DeviceType, Interface, InterfaceType, LoopbackType, + CURRENT_INTERFACE_VERSION, + }, exchange::{Exchange, ExchangeStatus}, globalconfig::GlobalConfig, link::{Link, LinkLinkType, LinkStatus}, From 14ebe9118bb8faac81cb3176c59d37e7c8f9663b Mon Sep 17 00:00:00 2001 From: Greg Mitchell Date: Mon, 4 Aug 2025 21:56:01 -0400 Subject: [PATCH 2/2] Update activator/src/process/link.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- activator/src/process/link.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activator/src/process/link.rs b/activator/src/process/link.rs index 224dc5230..84d863307 100644 --- a/activator/src/process/link.rs +++ b/activator/src/process/link.rs @@ -80,7 +80,7 @@ pub fn process_tunnel_event( ) { write!(&mut log_msg, " Error assigning side Z IP: {e}").unwrap(); } else { - write!(&mut log_msg, " Assigned side Z IP: {side_a_ip}").unwrap(); + write!(&mut log_msg, " Assigned side Z IP: {side_z_ip}").unwrap(); } } Err(e) => write!(&mut log_msg, " Error {e}").unwrap(),