Skip to content

Commit 6c8fb10

Browse files
committed
fix: clear cpi context account
1 parent a0c5813 commit 6c8fb10

File tree

3 files changed

+57
-43
lines changed

3 files changed

+57
-43
lines changed

programs/system/src/cpi_context/process_cpi_context.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ use pinocchio::{account_info::AccountInfo, program_error::ProgramError, pubkey::
1616
use solana_msg::msg;
1717

1818
use super::state::{deserialize_cpi_context_account, ZCpiContextAccount};
19-
use crate::{context::WrappedInstructionData, errors::SystemProgramError, Result};
19+
use crate::{
20+
context::WrappedInstructionData, cpi_context::state::deserialize_cpi_context_account_cleared,
21+
errors::SystemProgramError, Result,
22+
};
2023

2124
/// Diff:
2225
/// 1. return Cpi context instead of combined data.
@@ -107,18 +110,22 @@ pub fn set_cpi_context<'a, 'info, T: InstructionData<'a>>(
107110
// relay_fee
108111
// 2. Subsequent invocations check the proof and fee payer
109112

110-
let mut cpi_context_account =
111-
deserialize_cpi_context_account(cpi_context_account_info).map_err(ProgramError::from)?;
112-
113113
if instruction_data.cpi_context().unwrap().first_set_context {
114-
cpi_context_account.clear();
114+
let mut cpi_context_account =
115+
deserialize_cpi_context_account_cleared(cpi_context_account_info)
116+
.map_err(ProgramError::from)?;
115117
*cpi_context_account.fee_payer = fee_payer.into();
116118
cpi_context_account.store_data(&instruction_data)?;
117-
} else if *cpi_context_account.fee_payer == fee_payer && !cpi_context_account.is_empty() {
118-
cpi_context_account.store_data(&instruction_data)?;
119119
} else {
120-
msg!(format!(" {:?} != {:?}", fee_payer, cpi_context_account.fee_payer).as_str());
121-
return Err(SystemProgramError::CpiContextFeePayerMismatch.into());
120+
let mut cpi_context_account = deserialize_cpi_context_account(cpi_context_account_info)
121+
.map_err(ProgramError::from)?;
122+
123+
if *cpi_context_account.fee_payer == fee_payer && !cpi_context_account.is_empty() {
124+
cpi_context_account.store_data(&instruction_data)?;
125+
} else {
126+
msg!(format!(" {:?} != {:?}", fee_payer, cpi_context_account.fee_payer).as_str());
127+
return Err(SystemProgramError::CpiContextFeePayerMismatch.into());
128+
}
122129
}
123130

124131
Ok(())

programs/system/src/cpi_context/state.rs

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,6 @@ impl<'a> ZCpiContextAccount<'a> {
5656
&& self.output_data.is_empty()
5757
}
5858

59-
pub fn clear(&mut self) {
60-
self.new_addresses.clear();
61-
self.readonly_addresses.clear();
62-
self.readonly_accounts.clear();
63-
self.in_accounts.clear();
64-
self.out_accounts.clear();
65-
*self.output_data_len = 0.into();
66-
self.output_data.clear();
67-
self.remaining_data.fill(0);
68-
}
69-
7059
pub fn store_data<
7160
'b,
7261
T: light_compressed_account::instruction_data::traits::InstructionData<'b>,
@@ -185,6 +174,18 @@ impl Discriminator for ZCpiContextAccount<'_> {
185174

186175
pub fn deserialize_cpi_context_account<'a>(
187176
account_info: &AccountInfo,
177+
) -> std::result::Result<ZCpiContextAccount<'a>, ZeroCopyError> {
178+
deserialize_cpi_context_account_inner::<false>(account_info)
179+
}
180+
181+
pub fn deserialize_cpi_context_account_cleared<'a>(
182+
account_info: &AccountInfo,
183+
) -> std::result::Result<ZCpiContextAccount<'a>, ZeroCopyError> {
184+
deserialize_cpi_context_account_inner::<true>(account_info)
185+
}
186+
187+
fn deserialize_cpi_context_account_inner<'a, const CLEARED: bool>(
188+
account_info: &AccountInfo,
188189
) -> std::result::Result<ZCpiContextAccount<'a>, ZeroCopyError> {
189190
check_owner(&ID, account_info).map_err(|_| ZeroCopyError::IterFromOutOfBounds)?;
190191
let mut account_data = account_info
@@ -202,21 +203,34 @@ pub fn deserialize_cpi_context_account<'a>(
202203
let (associated_merkle_tree, data) =
203204
Ref::<&'a mut [u8], light_compressed_account::pubkey::Pubkey>::from_prefix(data)?;
204205

205-
let (new_addresses, data) =
206+
let (mut new_addresses, data) =
206207
ZeroCopyVecU8::<'a, CpiContextNewAddressParamsAssignedPacked>::from_bytes_at(data)?;
207-
let (readonly_addresses, data) =
208+
let (mut readonly_addresses, data) =
208209
ZeroCopyVecU8::<'a, ZPackedReadOnlyAddress>::from_bytes_at(data)?;
209-
let (readonly_accounts, data) =
210+
let (mut readonly_accounts, data) =
210211
ZeroCopyVecU8::<'a, ZPackedReadOnlyCompressedAccount>::from_bytes_at(data)?;
211-
let (in_accounts, data) = ZeroCopyVecU8::<'a, CpiContextInAccount>::from_bytes_at(data)?;
212-
let (out_accounts, data) = ZeroCopyVecU8::<'a, CpiContextOutAccount>::from_bytes_at(data)?;
213-
let (output_data_len, mut data) = Ref::<&'a mut [u8], U16>::from_prefix(data)?;
214-
let mut output_data = Vec::with_capacity(output_data_len.get() as usize);
215-
for _ in 0..output_data_len.get() {
216-
let (output_data_slice, inner_data) = ZeroCopySliceMut::<U16, u8>::from_bytes_at(data)?;
217-
output_data.push(output_data_slice);
218-
data = inner_data;
219-
}
212+
let (mut in_accounts, data) = ZeroCopyVecU8::<'a, CpiContextInAccount>::from_bytes_at(data)?;
213+
let (mut out_accounts, data) = ZeroCopyVecU8::<'a, CpiContextOutAccount>::from_bytes_at(data)?;
214+
let (mut output_data_len, mut data) = Ref::<&'a mut [u8], U16>::from_prefix(data)?;
215+
let output_data = if CLEARED {
216+
new_addresses.clear();
217+
readonly_addresses.clear();
218+
readonly_accounts.clear();
219+
in_accounts.clear();
220+
out_accounts.clear();
221+
output_data_len.set(0);
222+
// 65 CU
223+
data.fill(0);
224+
Vec::new()
225+
} else {
226+
let mut output_data = Vec::with_capacity(output_data_len.get() as usize);
227+
for _ in 0..output_data_len.get() {
228+
let (output_data_slice, inner_data) = ZeroCopySliceMut::<U16, u8>::from_bytes_at(data)?;
229+
output_data.push(output_data_slice);
230+
data = inner_data;
231+
}
232+
output_data
233+
};
220234

221235
Ok(ZCpiContextAccount {
222236
fee_payer,

programs/system/src/invoke_cpi/processor.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ pub use crate::Result;
55
use crate::{
66
accounts::account_traits::{CpiContextAccountTrait, InvokeAccounts, SignerAccounts},
77
context::WrappedInstructionData,
8-
cpi_context::process_cpi_context::process_cpi_context,
8+
cpi_context::{
9+
process_cpi_context::process_cpi_context, state::deserialize_cpi_context_account_cleared,
10+
},
911
invoke_cpi::verify_signer::cpi_signer_checks,
1012
processor::process::process,
1113
};
@@ -59,16 +61,7 @@ pub fn process_invoke_cpi<
5961

6062
// 4. clear cpi context account
6163
if cpi_context_inputs_len > 0 {
62-
// TODO: reimplement this doesn't work anymore
63-
// clear_cpi_context_account(accounts.get_cpi_context_account())?;
64+
deserialize_cpi_context_account_cleared(accounts.get_cpi_context_account().unwrap())?;
6465
}
6566
Ok(())
6667
}
67-
68-
/// Clear the CPI context account by setting the length to 0.
69-
pub fn clear_cpi_context_account(account_info: Option<&AccountInfo>) -> Result<()> {
70-
let mut data = account_info.unwrap().try_borrow_mut_data()?;
71-
let start_offset = 8 + 32 + 32;
72-
data[start_offset..start_offset + 4].copy_from_slice(&[0u8, 0u8, 0u8, 0u8]);
73-
Ok(())
74-
}

0 commit comments

Comments
 (0)