1212/// Obtained via [`AnchorAccount::cpi_handle`] (shared borrow) or by erasing a
1313/// [`CpiHandleMut`] produced from [`AnchorAccount::cpi_handle_mut`].
1414/// Most handles also participate in raw `AccountView` borrow validation before
15- /// CPI. Wrappers with their own borrow-state discipline (for example Slab) can
16- /// opt out so checked CPI doesn't reject sound Rust-exclusive access.
15+ /// CPI. Mutable handles from wrappers with their own borrow-state discipline
16+ /// (for example Slab) can opt out so checked CPI doesn't reject sound
17+ /// Rust-exclusive access.
1718///
1819/// Deliberately does NOT implement `Deref<Target = AccountView>` to
1920/// prevent accidental use with pinocchio's checked invoke builders.
@@ -30,22 +31,16 @@ pub struct CpiHandle<'a> {
3031/// erases into [`CpiHandle`] for invocation.
3132#[ derive( Clone , Copy ) ]
3233pub struct CpiHandleMut < ' a > {
33- view : & ' a AccountView ,
34- borrow_check : bool ,
34+ handle : CpiHandle < ' a > ,
3535}
3636
3737impl < ' a > CpiHandle < ' a > {
3838 #[ inline( always) ]
3939 pub fn readonly ( view : & ' a AccountView ) -> Self {
40- Self :: readonly_with_borrow_check ( view, true )
41- }
42-
43- #[ inline( always) ]
44- pub ( crate ) fn readonly_with_borrow_check ( view : & ' a AccountView , borrow_check : bool ) -> Self {
4540 Self {
4641 view,
4742 writable : false ,
48- borrow_check,
43+ borrow_check : true ,
4944 }
5045 }
5146
@@ -106,41 +101,49 @@ impl<'a> CpiHandle<'a> {
106101impl < ' a > CpiHandleMut < ' a > {
107102 #[ inline( always) ]
108103 pub fn writable ( view : & ' a mut AccountView ) -> Self {
109- Self :: with_borrow_check ( view, true )
104+ Self :: writable_with_borrow_check ( view, true )
110105 }
111106
112107 #[ inline( always) ]
113- pub ( crate ) fn with_borrow_check ( view : & ' a AccountView , borrow_check : bool ) -> Self {
114- Self { view, borrow_check }
108+ pub ( crate ) fn from_account ( view : & ' a AccountView ) -> Self {
109+ Self :: writable_with_borrow_check ( view, true )
110+ }
111+
112+ #[ inline( always) ]
113+ pub ( crate ) fn without_borrow_check ( view : & ' a AccountView ) -> Self {
114+ Self :: writable_with_borrow_check ( view, false )
115+ }
116+
117+ #[ inline( always) ]
118+ fn writable_with_borrow_check ( view : & ' a AccountView , borrow_check : bool ) -> Self {
119+ Self {
120+ handle : CpiHandle :: writable_with_borrow_check ( view, borrow_check) ,
121+ }
115122 }
116123
117124 /// The account's on-chain address.
118125 #[ inline( always) ]
119126 pub fn address ( & self ) -> & ' a Address {
120- self . view . address ( )
127+ self . handle . address ( )
121128 }
122129
123130 /// Mutable handles always erase to writable CPI handles.
124131 #[ inline( always) ]
125132 pub fn is_writable ( & self ) -> bool {
126- true
133+ self . handle . is_writable ( )
127134 }
128135
129136 /// Whether the underlying account is a signer on the transaction.
130137 #[ inline( always) ]
131138 pub fn is_signer ( & self ) -> bool {
132- self . view . is_signer ( )
139+ self . handle . is_signer ( )
133140 }
134141}
135142
136143impl < ' a > From < CpiHandleMut < ' a > > for CpiHandle < ' a > {
137144 #[ inline( always) ]
138145 fn from ( handle : CpiHandleMut < ' a > ) -> Self {
139- Self {
140- view : handle. view ,
141- writable : true ,
142- borrow_check : handle. borrow_check ,
143- }
146+ handle. handle
144147 }
145148}
146149
@@ -218,18 +221,6 @@ pub trait AnchorAccount: Deref<Target = Self::Data> + Sized {
218221 Ok ( ( ) )
219222 }
220223
221- /// Whether CPI handles derived from this wrapper should participate in the
222- /// raw `AccountView` borrow checks used by `program::invoke[_signed]`.
223- ///
224- /// Wrappers that keep live Rust references directly into account memory but
225- /// bypass pinocchio's borrow byte (for example Slab) override this to
226- /// return `false` and rely on their own `&self` / `&mut self` provenance.
227- #[ doc( hidden) ]
228- #[ inline( always) ]
229- fn cpi_requires_borrow_check ( & self ) -> bool {
230- true
231- }
232-
233224 /// v1-compatible alias for the account address.
234225 #[ cfg( feature = "compat" ) ]
235226 #[ inline( always) ]
@@ -255,7 +246,7 @@ pub trait AnchorAccount: Deref<Target = Self::Data> + Sized {
255246 /// it is alive. The handle's `is_writable` flag is `false`.
256247 #[ inline( always) ]
257248 fn cpi_handle ( & self ) -> CpiHandle < ' _ > {
258- CpiHandle :: readonly_with_borrow_check ( self . account ( ) , self . cpi_requires_borrow_check ( ) )
249+ CpiHandle :: readonly ( self . account ( ) )
259250 }
260251
261252 /// Obtain a writable CPI handle for this account.
@@ -280,10 +271,7 @@ pub trait AnchorAccount: Deref<Target = Self::Data> + Sized {
280271 #[ inline( always) ]
281272 fn try_cpi_handle_mut ( & mut self ) -> Result < CpiHandleMut < ' _ > , ProgramError > {
282273 require ! ( self . account( ) . is_writable( ) , ProgramError :: InvalidArgument ) ;
283- Ok ( CpiHandleMut :: with_borrow_check (
284- self . account ( ) ,
285- self . cpi_requires_borrow_check ( ) ,
286- ) )
274+ Ok ( CpiHandleMut :: from_account ( self . account ( ) ) )
287275 }
288276}
289277
0 commit comments