Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,38 @@ mod tests {
.is_err());
}

#[test]
fn test_admin_group_bits_exhaustion() {
let mut aligned_data = AlignedBitmap([0u8; 8]);
let mut allocator = IdAllocator::new((0, 32)).unwrap();

for expected in 0..32 {
let id = allocator.allocate(&mut aligned_data.0);
assert_eq!(id, Some(expected));
}
assert!(
allocator.allocate(&mut aligned_data.0).is_none(),
"allocation must fail when all 32 bits are exhausted"
);
}

#[test]
fn test_admin_group_bits_lowest_available() {
let mut aligned_data = AlignedBitmap([0u8; 8]);
let mut allocator = IdAllocator::new((0, 32)).unwrap();

assert_eq!(allocator.allocate(&mut aligned_data.0), Some(0));
assert_eq!(allocator.allocate(&mut aligned_data.0), Some(1));
assert_eq!(allocator.allocate(&mut aligned_data.0), Some(2));

// Allocate a specific higher bit, then verify next auto-allocate
// still returns the lowest free bit
allocator
.allocate_specific(&mut aligned_data.0, 10)
.unwrap();
assert_eq!(allocator.allocate(&mut aligned_data.0), Some(3));
}

#[test]
fn test_iter_allocated() {
let mut aligned_data = AlignedBitmap([0u8; 8]);
Expand Down
11 changes: 8 additions & 3 deletions smartcontract/programs/doublezero-serviceability/src/pda.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use solana_program::pubkey::Pubkey;

use crate::{
seeds::{
SEED_ACCESS_PASS, SEED_CONFIG, SEED_CONTRIBUTOR, SEED_DEVICE, SEED_DEVICE_TUNNEL_BLOCK,
SEED_DZ_PREFIX_BLOCK, SEED_EXCHANGE, SEED_GLOBALSTATE, SEED_LINK, SEED_LINK_IDS,
SEED_LOCATION, SEED_MULTICASTGROUP_BLOCK, SEED_MULTICAST_GROUP,
SEED_ACCESS_PASS, SEED_ADMIN_GROUP_BITS, SEED_CONFIG, SEED_CONTRIBUTOR, SEED_DEVICE,
SEED_DEVICE_TUNNEL_BLOCK, SEED_DZ_PREFIX_BLOCK, SEED_EXCHANGE, SEED_GLOBALSTATE, SEED_LINK,
SEED_LINK_IDS, SEED_LOCATION, SEED_MULTICASTGROUP_BLOCK, SEED_MULTICAST_GROUP,
SEED_MULTICAST_PUBLISHER_BLOCK, SEED_PERMISSION, SEED_PREFIX, SEED_PROGRAM_CONFIG,
SEED_SEGMENT_ROUTING_IDS, SEED_TENANT, SEED_TUNNEL_IDS, SEED_USER, SEED_USER_TUNNEL_BLOCK,
SEED_VRF_IDS,
Expand Down Expand Up @@ -169,5 +169,10 @@ pub fn get_resource_extension_pda(
Pubkey::find_program_address(&[SEED_PREFIX, SEED_VRF_IDS], program_id);
(pda, bump_seed, SEED_VRF_IDS)
}
crate::resource::ResourceType::AdminGroupBits => {
let (pda, bump_seed) =
Pubkey::find_program_address(&[SEED_PREFIX, SEED_ADMIN_GROUP_BITS], program_id);
(pda, bump_seed, SEED_ADMIN_GROUP_BITS)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub fn get_resource_extension_range(
ResourceType::LinkIds => ResourceExtensionRange::IdRange(0, 65535),
ResourceType::SegmentRoutingIds => ResourceExtensionRange::IdRange(1, 65535),
ResourceType::VrfIds => ResourceExtensionRange::IdRange(1, 1024),
ResourceType::AdminGroupBits => ResourceExtensionRange::IdRange(0, 32),
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub enum ResourceType {
LinkIds,
SegmentRoutingIds,
VrfIds,
AdminGroupBits,
}

impl fmt::Display for ResourceType {
Expand All @@ -29,6 +30,7 @@ impl fmt::Display for ResourceType {
ResourceType::LinkIds => write!(f, "LinkIds"),
ResourceType::SegmentRoutingIds => write!(f, "SegmentRoutingIds"),
ResourceType::VrfIds => write!(f, "VrfIds"),
ResourceType::AdminGroupBits => write!(f, "AdminGroupBits"),
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ pub const SEED_TUNNEL_IDS: &[u8] = b"tunnelids";
pub const SEED_LINK_IDS: &[u8] = b"linkids";
pub const SEED_SEGMENT_ROUTING_IDS: &[u8] = b"segmentroutingids";
pub const SEED_VRF_IDS: &[u8] = b"vrfids";
pub const SEED_ADMIN_GROUP_BITS: &[u8] = b"admingroupbits";
pub const SEED_PERMISSION: &[u8] = b"permission";
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,54 @@ mod tests {
assert_eq!(s, "ResourceExtensionOwned { account_type: ResourceExtension, owner: 11111111111111111111111111111111, bump_seed: 1, associated_with: 11111111111111111111111111111111, allocator: Id(IdAllocator { range: (0, 10), first_free_index: 0 }) }, allocated: []");
}

#[test]
fn test_admin_group_bits_resource_extension() {
let range = ResourceExtensionRange::IdRange(0, 32);
let mut buffer = vec![0u8; ResourceExtensionBorrowed::size(&range)];
let account_pk = Pubkey::new_unique();
let owner_pk = Pubkey::new_unique();
ResourceExtensionBorrowed::construct_resource(
&AccountInfo::new(
&account_pk,
false,
true,
&mut 0,
&mut buffer,
&owner_pk,
false,
0,
),
&owner_pk,
1,
&Pubkey::default(),
&range,
)
.unwrap();

// Allocate first 3 bits
let mut resext = ResourceExtensionBorrowed::inplace_from(&mut buffer[..]).unwrap();
assert_eq!(resext.allocate(1).unwrap(), IdOrIp::Id(0));
assert_eq!(resext.allocate(1).unwrap(), IdOrIp::Id(1));
assert_eq!(resext.allocate(1).unwrap(), IdOrIp::Id(2));

// Verify allocated state persists through re-parse
let resext_owned = ResourceExtensionOwned::try_from(&buffer[..]).unwrap();
assert_eq!(
resext_owned.iter_allocated(),
vec![IdOrIp::Id(0), IdOrIp::Id(1), IdOrIp::Id(2)]
);

// Exhaust remaining bits
let mut resext = ResourceExtensionBorrowed::inplace_from(&mut buffer[..]).unwrap();
for _ in 3..32 {
assert!(resext.allocate(1).is_ok());
}
assert_eq!(
resext.allocate(1).unwrap_err(),
DoubleZeroError::AllocationFailed
);
}

#[test]
fn test_resource_extension_borrowed_display_trait() {
let mut buffer =
Expand Down