Skip to content

Commit 99a8356

Browse files
committed
add location support to device update functionality
update device location instruction for reference counter management
1 parent 4b0f11a commit 99a8356

File tree

12 files changed

+544
-3
lines changed

12 files changed

+544
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ All notable changes to this project will be documented in this file.
5959
- serviceability: prevent device interface name duplication
6060
- Update serviceability and telemetry program instruction args to use the `BorshDeserializeIncremental` derive macro incremental, backward-compatible, deserialization of structs.
6161
- Add explicit signer checks for payer accounts across various processors to improve security and ensure correct transaction authorization.
62+
- Add the ability to update a Device’s location, managing the reference counters accordingly.
6263
- CLI
6364
- Removed `--bgp-community` option from `doublezero exchange create` since these values are now assigned automatically
6465
- Add `--next-bgp-community` option to `doublezero global-config set` so authorized users can control which bgp_community will be assigned next

smartcontract/cli/src/device/update.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ pub struct UpdateDeviceCliCommand {
3535
/// Contributor Pubkey (optional)
3636
#[arg(long, value_parser = validate_pubkey)]
3737
pub contributor: Option<String>,
38+
/// Location Pubkey (optional)
39+
#[arg(long, value_parser = validate_pubkey)]
40+
pub location: Option<String>,
3841
/// Management VRF name (optional)
3942
#[arg(long)]
4043
pub mgmt_vrf: Option<String>,
@@ -113,6 +116,10 @@ impl UpdateDeviceCliCommand {
113116
dz_prefixes: self.dz_prefixes,
114117
metrics_publisher,
115118
contributor_pk: contributor,
119+
location_pk: match &self.location {
120+
Some(location) => Some(Pubkey::from_str(location)?),
121+
None => None,
122+
},
116123
mgmt_vrf: self.mgmt_vrf,
117124
interfaces: None,
118125
max_users: self.max_users,
@@ -258,6 +265,9 @@ mod tests {
258265
contributor_pk: Some(Pubkey::from_str_const(
259266
"HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquBkcx",
260267
)),
268+
location_pk: Some(Pubkey::from_str_const(
269+
"HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquBkcx",
270+
)),
261271
mgmt_vrf: Some("default".to_string()),
262272
interfaces: None,
263273
max_users: Some(1025),
@@ -275,6 +285,7 @@ mod tests {
275285
dz_prefixes: Some("1.2.3.4/32".parse().unwrap()),
276286
metrics_publisher: Some("HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquBkcx".to_string()),
277287
contributor: Some("HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquBkcx".to_string()),
288+
location: Some("HQ2UUt18uJqKaQFJhgV9zaTdQxUZjNrsKFgoEDquBkcx".to_string()),
278289
mgmt_vrf: Some("default".to_string()),
279290
max_users: Some(1025),
280291
users_count: Some(0),
@@ -364,6 +375,7 @@ mod tests {
364375
public_ip: None,
365376
dz_prefixes: None,
366377
metrics_publisher: None,
378+
location: None,
367379
contributor: None,
368380
mgmt_vrf: None,
369381
max_users: Some(255),
@@ -453,6 +465,7 @@ mod tests {
453465
public_ip: Some([10, 20, 30, 40].into()),
454466
dz_prefixes: None,
455467
metrics_publisher: None,
468+
location: None,
456469
contributor: None,
457470
mgmt_vrf: None,
458471
max_users: None,

smartcontract/programs/doublezero-serviceability/src/error.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ pub enum DoubleZeroError {
121121
InvalidInterfaceType, // variant 57
122122
#[error("Invalid Loopback Type")]
123123
InvalidLoopbackType, // variant 58
124+
#[error("Invalid Actual Location")]
125+
InvalidActualLocation, // variant 59
124126
}
125127

126128
impl From<DoubleZeroError> for ProgramError {
@@ -185,6 +187,7 @@ impl From<DoubleZeroError> for ProgramError {
185187
DoubleZeroError::InterfaceAlreadyExists => ProgramError::Custom(56),
186188
DoubleZeroError::InvalidInterfaceType => ProgramError::Custom(57),
187189
DoubleZeroError::InvalidLoopbackType => ProgramError::Custom(58),
190+
DoubleZeroError::InvalidActualLocation => ProgramError::Custom(59),
188191
}
189192
}
190193
}
@@ -250,6 +253,7 @@ impl From<u32> for DoubleZeroError {
250253
56 => DoubleZeroError::InterfaceAlreadyExists,
251254
57 => DoubleZeroError::InvalidInterfaceType,
252255
58 => DoubleZeroError::InvalidLoopbackType,
256+
59 => DoubleZeroError::InvalidActualLocation,
253257
_ => DoubleZeroError::Custom(e),
254258
}
255259
}
@@ -335,6 +339,7 @@ mod tests {
335339
InterfaceAlreadyExists,
336340
InvalidInterfaceType,
337341
InvalidLoopbackType,
342+
InvalidActualLocation,
338343
];
339344
for err in variants {
340345
let pe: ProgramError = err.clone().into();

smartcontract/programs/doublezero-serviceability/src/processors/device/update.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,16 @@ use crate::{
22
error::DoubleZeroError,
33
globalstate::globalstate_get,
44
helper::*,
5-
state::{accounttype::AccountType, contributor::Contributor, device::*},
5+
state::{accounttype::AccountType, contributor::Contributor, device::*, location::Location},
66
};
77
use borsh::BorshSerialize;
88
use borsh_incremental::BorshDeserializeIncremental;
99
use core::fmt;
1010
use doublezero_program_common::{types::NetworkV4List, validate_account_code};
11-
#[cfg(test)]
12-
use solana_program::msg;
1311
use solana_program::{
1412
account_info::{next_account_info, AccountInfo},
1513
entrypoint::ProgramResult,
14+
msg,
1615
pubkey::Pubkey,
1716
};
1817

@@ -71,6 +70,9 @@ pub fn process_update_device(
7170

7271
let device_account = next_account_info(accounts_iter)?;
7372
let contributor_account = next_account_info(accounts_iter)?;
73+
// Update location accounts (old and new)
74+
let location_old_account = next_account_info(accounts_iter)?;
75+
let location_new_account = next_account_info(accounts_iter)?;
7476
let globalstate_account = next_account_info(accounts_iter)?;
7577
let payer_account = next_account_info(accounts_iter)?;
7678
let system_program = next_account_info(accounts_iter)?;
@@ -147,6 +149,37 @@ pub fn process_update_device(
147149
if let Some(max_users) = value.max_users {
148150
device.max_users = max_users;
149151
}
152+
if location_old_account.key != location_new_account.key {
153+
let mut location_old = Location::try_from(location_old_account)?;
154+
let mut location_new = Location::try_from(location_new_account)?;
155+
if device.location_pk != *location_old_account.key {
156+
msg!(
157+
"Invalid location account. Device location_pk: {}, location_old_account: {}",
158+
device.location_pk,
159+
location_old_account.key
160+
);
161+
return Err(DoubleZeroError::InvalidActualLocation.into());
162+
}
163+
164+
location_old.reference_count = location_old.reference_count.saturating_sub(1);
165+
location_new.reference_count = location_new.reference_count.saturating_add(1);
166+
167+
// Set new location pk in device
168+
device.location_pk = *location_new_account.key;
169+
170+
account_write(
171+
location_old_account,
172+
&location_old,
173+
payer_account,
174+
system_program,
175+
)?;
176+
account_write(
177+
location_new_account,
178+
&location_new,
179+
payer_account,
180+
system_program,
181+
)?;
182+
}
150183

151184
account_write(device_account, &device, payer_account, system_program)?;
152185

smartcontract/programs/doublezero-serviceability/tests/accesspass_allow_multiple_ip.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ async fn test_accesspass_allow_multiple_ip() {
215215
vec![
216216
AccountMeta::new(device_pubkey, false),
217217
AccountMeta::new(contributor_pubkey, false),
218+
AccountMeta::new(location_pubkey, false),
219+
AccountMeta::new(location_pubkey, false),
218220
AccountMeta::new(globalstate_pubkey, false),
219221
],
220222
&payer,

smartcontract/programs/doublezero-serviceability/tests/device_test.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ async fn test_device() {
208208
vec![
209209
AccountMeta::new(device_pubkey, false),
210210
AccountMeta::new(contributor_pubkey, false),
211+
AccountMeta::new(location_pubkey, false),
212+
AccountMeta::new(location_pubkey, false),
211213
AccountMeta::new(globalstate_pubkey, false),
212214
],
213215
&payer,
@@ -340,6 +342,8 @@ async fn test_device() {
340342
vec![
341343
AccountMeta::new(device_pubkey, false),
342344
AccountMeta::new(contributor_pubkey, false),
345+
AccountMeta::new(location_pubkey, false),
346+
AccountMeta::new(location_pubkey, false),
343347
AccountMeta::new(globalstate_pubkey, false),
344348
],
345349
&payer,
@@ -492,6 +496,8 @@ async fn test_device_update_metrics_publisher_by_foundation_allowlist_account()
492496
vec![
493497
AccountMeta::new(device_pubkey, false),
494498
AccountMeta::new(contributor_pubkey, false),
499+
AccountMeta::new(location_pubkey, false),
500+
AccountMeta::new(location_pubkey, false),
495501
AccountMeta::new(globalstate_pubkey, false),
496502
],
497503
&payer,
@@ -525,6 +531,8 @@ async fn test_device_update_metrics_publisher_by_foundation_allowlist_account()
525531
vec![
526532
AccountMeta::new(device_pubkey, false),
527533
AccountMeta::new(contributor_pubkey, false),
534+
AccountMeta::new(location_pubkey, false),
535+
AccountMeta::new(location_pubkey, false),
528536
AccountMeta::new(globalstate_pubkey, false),
529537
],
530538
&payer,

0 commit comments

Comments
 (0)