11use crate :: {
22 error:: DoubleZeroError ,
33 pda:: { get_index_pda, get_resource_extension_pda} ,
4- processors:: resource:: deallocate_ip,
4+ processors:: { resource:: deallocate_ip, validation :: validate_program_account } ,
55 resource:: ResourceType ,
66 seeds:: SEED_MULTICAST_GROUP ,
77 serializer:: try_acc_close,
@@ -25,17 +25,14 @@ pub struct MulticastGroupDeactivateArgs {
2525 /// When false, legacy behavior is used (no deallocation).
2626 #[ incremental( default = false ) ]
2727 pub use_onchain_deallocation : bool ,
28- /// When true, close the associated Index account alongside the multicast group.
29- #[ incremental( default = false ) ]
30- pub close_index : bool ,
3128}
3229
3330impl fmt:: Debug for MulticastGroupDeactivateArgs {
3431 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
3532 write ! (
3633 f,
37- "use_onchain_deallocation: {}, close_index: {} " ,
38- self . use_onchain_deallocation, self . close_index
34+ "use_onchain_deallocation: {}" ,
35+ self . use_onchain_deallocation
3936 )
4037 }
4138}
@@ -51,26 +48,18 @@ pub fn process_closeaccount_multicastgroup(
5148 let owner_account = next_account_info ( accounts_iter) ?;
5249 let globalstate_account = next_account_info ( accounts_iter) ?;
5350
54- // Optional accounts (before payer/system):
55- // Account layout WITH deallocation + index:
51+ // Account layout WITH deallocation:
5652 // [multicastgroup, owner, globalstate, multicast_group_block, index, payer, system]
57- // Account layout WITHOUT deallocation, with index :
53+ // Account layout WITHOUT deallocation:
5854 // [multicastgroup, owner, globalstate, index, payer, system]
59- // Legacy (no deallocation, no index):
60- // [multicastgroup, owner, globalstate, payer, system]
6155 let resource_extension_account = if value. use_onchain_deallocation {
6256 let multicast_group_block_ext = next_account_info ( accounts_iter) ?;
6357 Some ( multicast_group_block_ext)
6458 } else {
6559 None
6660 } ;
6761
68- let index_account = if value. close_index {
69- Some ( next_account_info ( accounts_iter) ?)
70- } else {
71- None
72- } ;
73-
62+ let index_account = next_account_info ( accounts_iter) ?;
7463 let payer_account = next_account_info ( accounts_iter) ?;
7564 let system_program = next_account_info ( accounts_iter) ?;
7665
@@ -80,25 +69,24 @@ pub fn process_closeaccount_multicastgroup(
8069 // Check if the payer is a signer
8170 assert ! ( payer_account. is_signer, "Payer must be a signer" ) ;
8271
83- // Check the owner of the accounts
84- assert_eq ! (
85- multicastgroup_account. owner, program_id,
86- "Invalid PDA Account Owner"
72+ // Validate accounts
73+ validate_program_account ! (
74+ multicastgroup_account,
75+ program_id,
76+ writable = true ,
77+ "MulticastGroup"
8778 ) ;
88- assert_eq ! (
89- globalstate_account. owner, program_id,
90- "Invalid GlobalState Account Owner"
79+ validate_program_account ! (
80+ globalstate_account,
81+ program_id,
82+ writable = false ,
83+ "GlobalState"
9184 ) ;
9285 assert_eq ! (
9386 * system_program. unsigned_key( ) ,
9487 solana_system_interface:: program:: ID ,
9588 "Invalid System Program Account Owner"
9689 ) ;
97- // Check if the account is writable
98- assert ! (
99- multicastgroup_account. is_writable,
100- "PDA Account is not writable"
101- ) ;
10290
10391 let globalstate = GlobalState :: try_from ( globalstate_account) ?;
10492 if globalstate. activator_authority_pk != * payer_account. key {
@@ -119,25 +107,14 @@ pub fn process_closeaccount_multicastgroup(
119107 // Deallocate multicast_ip from ResourceExtension if account provided
120108 // Deallocation is idempotent - safe to call even if resource wasn't allocated
121109 if let Some ( multicast_group_block_ext) = resource_extension_account {
122- // Validate multicast_group_block_ext (MulticastGroupBlock - global)
123- assert_eq ! (
124- multicast_group_block_ext. owner, program_id,
125- "Invalid ResourceExtension Account Owner for MulticastGroupBlock"
126- ) ;
127- assert ! (
128- multicast_group_block_ext. is_writable,
129- "ResourceExtension Account for MulticastGroupBlock is not writable"
130- ) ;
131- assert ! (
132- !multicast_group_block_ext. data_is_empty( ) ,
133- "ResourceExtension Account for MulticastGroupBlock is empty"
134- ) ;
135-
136- let ( expected_multicast_group_pda, _, _) =
110+ let ( expected_pda, _, _) =
137111 get_resource_extension_pda ( program_id, ResourceType :: MulticastGroupBlock ) ;
138- assert_eq ! (
139- multicast_group_block_ext. key, & expected_multicast_group_pda,
140- "Invalid ResourceExtension PDA for MulticastGroupBlock"
112+ validate_program_account ! (
113+ multicast_group_block_ext,
114+ program_id,
115+ writable = true ,
116+ pda = & expected_pda,
117+ "MulticastGroupBlock"
141118 ) ;
142119
143120 // Deallocate multicast_ip from global MulticastGroupBlock
@@ -149,22 +126,25 @@ pub fn process_closeaccount_multicastgroup(
149126
150127 try_acc_close ( multicastgroup_account, owner_account) ?;
151128
152- // Close the Index account if provided
153- if let Some ( index_acc) = index_account {
154- assert_eq ! ( index_acc. owner, program_id, "Invalid Index Account Owner" ) ;
155- assert ! ( index_acc. is_writable, "Index Account is not writable" ) ;
156-
129+ // Close the Index account (skip for pre-migration accounts using Pubkey::default())
130+ if * index_account. key != Pubkey :: default ( ) {
157131 let ( expected_index_pda, _) =
158132 get_index_pda ( program_id, SEED_MULTICAST_GROUP , & multicastgroup. code ) ;
159- assert_eq ! ( index_acc. key, & expected_index_pda, "Invalid Index Pubkey" ) ;
133+ validate_program_account ! (
134+ index_account,
135+ program_id,
136+ writable = true ,
137+ pda = & expected_index_pda,
138+ "Index"
139+ ) ;
160140
161- let index = Index :: try_from ( index_acc ) ?;
141+ let index = Index :: try_from ( index_account ) ?;
162142 assert_eq ! (
163143 index. pk, * multicastgroup_account. key,
164144 "Index does not point to this MulticastGroup"
165145 ) ;
166146
167- try_acc_close ( index_acc , payer_account) ?;
147+ try_acc_close ( index_account , payer_account) ?;
168148 }
169149
170150 #[ cfg( test) ]
0 commit comments