Skip to content
Merged
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ All notable changes to this project will be documented in this file.
- The QA alldevices test now considers device location and connects hosts to nearby devices
- QA agent and tests now support doublezero connect ibrl's --allocate-addr flag
- The QA alldevices test now publishes success/failure metrics to InfluxDB in support of rfc12
- Onchain programs
- Fix CreateMulticastGroup to use incremented globalstate.account_index for PDA derivation instead of client-provided index, to ensure the contract is the authoritative source for account indices
- ReactivateMulticastGroup now enforces that the multicast group status must be Suspended before reactivation, returning InvalidStatus otherwise; negative-path regression tests were added.

## [v0.8.0](https://github.com/malbeclabs/doublezero/compare/client/v0.7.1...client/v0.8.0) – 2025-12-02

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ pub fn process_reactivate_multicastgroup(
}

let mut multicastgroup: MulticastGroup = MulticastGroup::try_from(multicastgroup_account)?;

if multicastgroup.status != MulticastGroupStatus::Suspended {
return Err(DoubleZeroError::InvalidStatus.into());
}

multicastgroup.status = MulticastGroupStatus::Activated;

try_acc_write(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,78 @@ async fn test_multicastgroup_create_with_wrong_index_fails() {

println!("🟢 End test_multicastgroup_create_with_wrong_index_fails");
}

#[tokio::test]
async fn test_multicastgroup_reactivate_invalid_status_fails() {
let (mut banks_client, program_id, payer, recent_blockhash) = init_test().await;

println!("🟢 Start test_multicastgroup_reactivate_invalid_status_fails");

let (program_config_pubkey, _) = get_program_config_pda(&program_id);
let (globalstate_pubkey, _) = get_globalstate_pda(&program_id);

println!("1. Global Initialization...");
execute_transaction(
&mut banks_client,
recent_blockhash,
program_id,
DoubleZeroInstruction::InitGlobalState(),
vec![
AccountMeta::new(program_config_pubkey, false),
AccountMeta::new(globalstate_pubkey, false),
],
&payer,
)
.await;

println!("2. Create MulticastGroup (status Pending)...");
let globalstate_account = get_globalstate(&mut banks_client, globalstate_pubkey).await;
let (multicastgroup_pubkey, _) =
get_multicastgroup_pda(&program_id, globalstate_account.account_index + 1);

execute_transaction(
&mut banks_client,
recent_blockhash,
program_id,
DoubleZeroInstruction::CreateMulticastGroup(MulticastGroupCreateArgs {
code: "reactivate-test".to_string(),
max_bandwidth: 1000,
owner: Pubkey::new_unique(),
}),
vec![
AccountMeta::new(multicastgroup_pubkey, false),
AccountMeta::new(globalstate_pubkey, false),
],
&payer,
)
.await;

let multicastgroup = get_account_data(&mut banks_client, multicastgroup_pubkey)
.await
.expect("Unable to get Account")
.get_multicastgroup()
.unwrap();
assert_eq!(multicastgroup.status, MulticastGroupStatus::Pending);

println!("3. Attempt to reactivate while not Suspended (should fail)...");
let result = try_execute_transaction(
&mut banks_client,
recent_blockhash,
program_id,
DoubleZeroInstruction::ReactivateMulticastGroup(MulticastGroupReactivateArgs {}),
vec![
AccountMeta::new(multicastgroup_pubkey, false),
AccountMeta::new(globalstate_pubkey, false),
],
&payer,
)
.await;

assert!(
result.is_err(),
"Reactivate should fail when status is not Suspended"
);

println!("✅ Correctly rejected ReactivateMulticastGroup for non-Suspended status");
println!("🟢 End test_multicastgroup_reactivate_invalid_status_fails");
}
Loading