Skip to main content

anchor_lang/
traits.rs

1#[cfg(feature = "compat")]
2use pinocchio::account::{Ref, RefMut};
3use {
4    crate::require,
5    core::ops::Deref,
6    pinocchio::{
7        account::{AccountView, NOT_BORROWED},
8        address::Address,
9        instruction::InstructionAccount,
10    },
11    solana_program_error::{ProgramError, ProgramResult},
12};
13
14/// Zero-cost CPI handle that borrows an anchor account at the Rust level.
15///
16/// Obtained via [`AnchorAccount::cpi_handle`] (shared borrow) or by erasing a
17/// [`CpiHandleMut`] produced from [`AnchorAccount::cpi_handle_mut`].
18/// Handles participate in raw `AccountView` borrow validation before CPI by
19/// default. Wrappers with their own borrow-state discipline may opt out when
20/// the CPI account meta guarantees the callee cannot mutate the account.
21///
22/// Deliberately does NOT implement `Deref<Target = AccountView>` to
23/// prevent accidental use with pinocchio's checked invoke builders.
24#[derive(Clone, Copy)]
25pub struct CpiHandle<'a> {
26    view: &'a AccountView,
27    writable: bool,
28    borrow_check: bool,
29    relax_readonly_borrow: bool,
30}
31
32/// Typed mutable CPI handle for API-facing CPI account structs.
33///
34/// This carries the exclusive-borrow provenance at construction time, then
35/// erases into [`CpiHandle`] for invocation.
36#[derive(Clone, Copy)]
37pub struct CpiHandleMut<'a> {
38    view: &'a AccountView,
39    borrow_check: bool,
40}
41
42pub(crate) struct CpiBorrowGuard {
43    borrow_state: *mut u8,
44    restore_to: u8,
45}
46
47impl<'a> CpiHandle<'a> {
48    #[inline(always)]
49    pub fn readonly(view: &'a AccountView) -> Self {
50        Self::readonly_with_borrow_check(view, true)
51    }
52
53    #[inline(always)]
54    pub(crate) fn readonly_with_borrow_check(view: &'a AccountView, borrow_check: bool) -> Self {
55        Self::readonly_with_flags(view, borrow_check, false)
56    }
57
58    #[inline(always)]
59    pub(crate) fn readonly_with_flags(
60        view: &'a AccountView,
61        borrow_check: bool,
62        relax_readonly_borrow: bool,
63    ) -> Self {
64        Self {
65            view,
66            writable: false,
67            borrow_check,
68            relax_readonly_borrow,
69        }
70    }
71
72    #[inline(always)]
73    pub fn writable(view: &'a mut AccountView) -> Self {
74        Self::writable_with_borrow_check(view, true)
75    }
76
77    #[inline(always)]
78    pub(crate) fn writable_with_borrow_check(view: &'a AccountView, borrow_check: bool) -> Self {
79        Self {
80            view,
81            writable: true,
82            borrow_check,
83            relax_readonly_borrow: false,
84        }
85    }
86
87    /// The account's on-chain address.
88    ///
89    /// Returns a reference with the inner `'a` lifetime so callers can
90    /// build `InstructionAccount<'a>` values without tying the result to
91    /// the borrow of `&self`.
92    #[inline(always)]
93    pub fn address(&self) -> &'a Address {
94        self.view.address()
95    }
96
97    /// Whether this handle was obtained via `cpi_handle_mut`.
98    #[inline(always)]
99    pub fn is_writable(&self) -> bool {
100        self.writable
101    }
102
103    /// Whether the underlying account is a signer on the transaction.
104    #[inline(always)]
105    pub fn is_signer(&self) -> bool {
106        self.view.is_signer()
107    }
108
109    /// Erase to a readonly CPI handle.
110    ///
111    /// Used by `#[account_meta(duplicate_readonly)]` so a `CpiHandle` or
112    /// `CpiHandleMut` field can emit a second readonly meta/handle pair.
113    #[inline(always)]
114    pub fn into_readonly(self) -> CpiHandle<'a> {
115        Self::readonly_with_flags(self.view, self.borrow_check, self.relax_readonly_borrow)
116    }
117
118    /// Access the underlying `AccountView` for CPI account construction.
119    ///
120    /// Restricted to the crate so external code cannot extract the view
121    /// and pass it to pinocchio's checked invoke.
122    #[inline(always)]
123    pub(crate) fn account_view(&self) -> &'a AccountView {
124        self.view
125    }
126
127    #[inline(always)]
128    pub(crate) fn requires_borrow_check(&self) -> bool {
129        self.borrow_check
130    }
131
132    #[inline(always)]
133    pub(crate) fn enter_cpi(&self) -> Option<CpiBorrowGuard> {
134        if !self.writable && self.relax_readonly_borrow {
135            let borrow_state = self.view.account_ptr().cast_mut().cast::<u8>();
136            // Mutable Slab wrappers pin the runtime borrow state at `0` while
137            // the wrapper is alive. For readonly CPIs that state is too
138            // strong: the callee only needs shared borrows, and readonly metas
139            // prevent writes. Downgrade to a single shared borrow for the CPI
140            // and restore the exclusive marker afterwards.
141            unsafe { *borrow_state = NOT_BORROWED - 1 };
142            Some(CpiBorrowGuard {
143                borrow_state,
144                restore_to: 0,
145            })
146        } else {
147            None
148        }
149    }
150}
151
152impl<'a> CpiHandleMut<'a> {
153    #[inline(always)]
154    pub fn writable(view: &'a mut AccountView) -> Self {
155        Self::writable_with_borrow_check(view, true)
156    }
157
158    #[inline(always)]
159    pub(crate) fn without_borrow_check(view: &'a AccountView) -> Self {
160        Self::writable_with_borrow_check(view, false)
161    }
162
163    #[inline(always)]
164    fn writable_with_borrow_check(view: &'a AccountView, borrow_check: bool) -> Self {
165        Self { view, borrow_check }
166    }
167
168    /// The account's on-chain address.
169    #[inline(always)]
170    pub fn address(&self) -> &'a Address {
171        self.view.address()
172    }
173
174    /// Mutable handles always erase to writable CPI handles.
175    #[inline(always)]
176    pub fn is_writable(&self) -> bool {
177        true
178    }
179
180    /// Whether the underlying account is a signer on the transaction.
181    #[inline(always)]
182    pub fn is_signer(&self) -> bool {
183        self.view.is_signer()
184    }
185
186    /// Erase to a readonly [`CpiHandle`].
187    ///
188    /// Used by `#[account_meta(duplicate_readonly)]` so a writable field can
189    /// still emit a second readonly meta/handle pair.
190    #[inline(always)]
191    pub fn into_readonly(self) -> CpiHandle<'a> {
192        CpiHandle::readonly_with_borrow_check(self.view, self.borrow_check)
193    }
194}
195
196impl<'a> From<CpiHandleMut<'a>> for CpiHandle<'a> {
197    #[inline(always)]
198    fn from(handle: CpiHandleMut<'a>) -> Self {
199        Self {
200            view: handle.view,
201            writable: true,
202            borrow_check: handle.borrow_check,
203            relax_readonly_borrow: false,
204        }
205    }
206}
207
208impl Drop for CpiBorrowGuard {
209    fn drop(&mut self) {
210        unsafe { *self.borrow_state = self.restore_to };
211    }
212}
213
214pub(crate) fn enter_cpi<'a>(handles: &[CpiHandle<'a>]) -> alloc::vec::Vec<CpiBorrowGuard> {
215    let mut guards = alloc::vec::Vec::new();
216    for handle in handles {
217        if let Some(guard) = handle.enter_cpi() {
218            guards.push(guard);
219        }
220    }
221    guards
222}
223
224/// Converts a CPI accounts struct into instruction metadata and handles.
225///
226/// Implemented by generated CPI accounts structs. Each field maps to an
227/// [`InstructionAccount`] (address + writable/signer flags) and an erased
228/// [`CpiHandle`] for the actual invocation.
229pub trait ToCpiAccounts<'a> {
230    /// Produce instruction account metadata for the CPI instruction.
231    fn to_instruction_accounts(&self) -> alloc::vec::Vec<InstructionAccount<'a>>;
232
233    /// Collect all CPI handles for the invocation.
234    fn to_cpi_handles(&self) -> alloc::vec::Vec<CpiHandle<'a>>;
235
236    /// Parallel to [`to_instruction_accounts`]: `true` at each index where an
237    /// optional field was `None` and a program-id sentinel meta was emitted.
238    ///
239    /// The CPI invoker may skip a matching handle only for these indices.
240    /// Required accounts whose address equals the callee program id must be
241    /// `false` here so they still require a handle.
242    fn optional_account_sentinel_flags(&self) -> alloc::vec::Vec<bool>;
243}
244
245pub trait AnchorAccount: Deref<Target = Self::Data> + Sized {
246    type Data;
247
248    /// Whether this account wrapper requires the transaction account meta to
249    /// be marked as a signer in generated clients and CPI account structs.
250    const IS_SIGNER: bool = false;
251
252    /// Minimum account data length for this type. When > 0, PDA
253    /// verification can skip `sol_curve_validate_point`: a non-empty
254    /// account was created via CreateAccount/Allocate (which requires
255    /// signing), and `invoke_signed` already includes the curve check.
256    ///
257    /// Non-empty wrappers override this with their schema-specific minimum.
258    /// UncheckedAccount / zero-data wrappers leave it at `0` (forces the curve
259    /// check).
260    const MIN_DATA_LEN: usize = 0;
261
262    /// Whether readonly CPI handles borrowed from a mutable wrapper need their
263    /// runtime borrow marker temporarily relaxed during CPI entry.
264    ///
265    /// Wrappers that keep an exclusive marker alive after `load_mut()` (for
266    /// example `Account<T>` / `Slab<H, T>` and `SerializedAccount<T, S>`)
267    /// override this so derive-generated readonly CPI accounts can preserve
268    /// compatibility without reopening writable aliasing.
269    const RELAX_READONLY_CPI_BORROW_FROM_MUT: bool = false;
270
271    fn load(view: AccountView) -> core::result::Result<Self, ProgramError>;
272
273    /// Load an account for mutable access.
274    ///
275    /// # Safety
276    ///
277    /// No other live `&mut` to the same account data may exist while the
278    /// returned value is alive. In derive-generated code the bitvec
279    /// duplicate-account check enforces this; direct callers must uphold
280    /// it themselves.
281    ///
282    /// Default impl validates `is_writable` and delegates to `load()`.
283    /// Data-carrying wrappers (`Account<T>`, `BorshAccount<T>`, `Slab<H, T>`)
284    /// override to use `borrow_unchecked_mut` for write provenance.
285    /// `Signer` overrides with a fused `is_signer` + `is_writable` check.
286    #[inline(always)]
287    unsafe fn load_mut(view: AccountView) -> core::result::Result<Self, ProgramError> {
288        if !view.is_writable() {
289            return Err(crate::ErrorCode::ConstraintMut.into());
290        }
291        Self::load(view)
292    }
293
294    /// Like [`load_mut`], but called right after
295    /// `AccountInitialize::create_and_initialize`. Owner, discriminator,
296    /// and min-length checks are tautologies on this path, so data-carrying
297    /// wrappers override to skip them. Default forwards to [`load_mut`].
298    ///
299    /// # Safety
300    ///
301    /// Same as [`load_mut`]: no other live `&mut` to the same account data.
302    ///
303    /// [`load_mut`]: Self::load_mut
304    #[inline(always)]
305    unsafe fn load_mut_after_init(view: AccountView) -> core::result::Result<Self, ProgramError> {
306        Self::load_mut(view)
307    }
308
309    fn account(&self) -> &AccountView;
310
311    fn exit(&mut self) -> ProgramResult {
312        Ok(())
313    }
314
315    /// v1-compatible alias for the account address.
316    #[cfg(feature = "compat")]
317    #[inline(always)]
318    fn key(&self) -> crate::solana_program::pubkey::Pubkey {
319        *self.account().address()
320    }
321
322    /// Obtain a read-only CPI handle for this account.
323    ///
324    /// The handle borrows `self`, preventing mutable typed access while
325    /// it is alive. The handle's `is_writable` flag is `false`.
326    #[inline(always)]
327    fn cpi_handle(&self) -> CpiHandle<'_> {
328        CpiHandle::readonly(self.account())
329    }
330
331    /// Obtain a writable CPI handle for this account.
332    ///
333    /// The handle borrows `self` mutably, preventing any typed access
334    /// while it is alive.
335    ///
336    /// # Panics
337    ///
338    /// Panics if the underlying account is not marked writable in
339    /// the transaction.
340    #[inline(always)]
341    fn cpi_handle_mut(&mut self) -> CpiHandleMut<'_> {
342        self.try_cpi_handle_mut()
343            .expect("cpi_handle_mut called on a read-only account")
344    }
345
346    /// Fallible variant of [`cpi_handle_mut`](Self::cpi_handle_mut).
347    ///
348    /// Returns [`ProgramError::InvalidArgument`] when the underlying account
349    /// is not marked writable in the transaction.
350    #[inline(always)]
351    fn try_cpi_handle_mut(&mut self) -> Result<CpiHandleMut<'_>, ProgramError> {
352        require!(self.account().is_writable(), ProgramError::InvalidArgument);
353        Ok(CpiHandleMut::writable_with_borrow_check(
354            self.account(),
355            true,
356        ))
357    }
358}
359
360/// Account wrapper capability for `#[account(realloc = ...)]`.
361///
362/// The derive emits a call to this trait instead of deciding realloc safety
363/// from syntactic type names. That lets rustc resolve aliases and wrapper
364/// forwards normally: unsupported wrappers simply do not implement the trait.
365pub trait AccountRealloc: AnchorAccount {
366    fn realloc_account(
367        &mut self,
368        new_space: usize,
369        payer: AccountView,
370        zero: bool,
371    ) -> ProgramResult;
372}
373
374/// Account wrapper capability for `#[account(close = ...)]`.
375///
376/// The derive emits a call to this trait instead of deciding close support
377/// from syntactic type names. That lets rustc resolve aliases and wrapper
378/// forwards normally: unsupported wrappers (notably `UncheckedAccount`)
379/// simply do not implement the trait.
380#[diagnostic::on_unimplemented(
381    message = "`#[account(close = ...)]` is not supported on `UncheckedAccount`",
382    note = "use a typed account wrapper or close the raw account manually"
383)]
384pub trait AccountClose: AnchorAccount {
385    fn close(&mut self, destination: AccountView) -> ProgramResult;
386}
387
388/// Account-like value that can be passed into a CPI account struct.
389///
390/// This is the v2 equivalent of v1's `ToAccountInfo` for CPI construction:
391/// callers get a [`CpiHandle`] instead of cloning an `AccountInfo`.
392pub trait ToCpiHandle {
393    fn to_cpi_handle(&self) -> CpiHandle<'_>;
394}
395
396/// Account-like value that can be passed into a writable CPI account slot.
397pub trait ToCpiHandleMut {
398    fn try_to_cpi_handle_mut(&mut self) -> Result<CpiHandleMut<'_>, ProgramError>;
399
400    #[inline(always)]
401    fn to_cpi_handle_mut(&mut self) -> CpiHandleMut<'_> {
402        self.try_to_cpi_handle_mut()
403            .expect("to_cpi_handle_mut called on a read-only account")
404    }
405}
406
407impl<T: ToCpiHandle + ?Sized> ToCpiHandle for &T {
408    #[inline(always)]
409    fn to_cpi_handle(&self) -> CpiHandle<'_> {
410        (*self).to_cpi_handle()
411    }
412}
413
414impl<T: ToCpiHandle + ?Sized> ToCpiHandle for &mut T {
415    #[inline(always)]
416    fn to_cpi_handle(&self) -> CpiHandle<'_> {
417        (**self).to_cpi_handle()
418    }
419}
420
421impl<T: ToCpiHandleMut + ?Sized> ToCpiHandleMut for &mut T {
422    #[inline(always)]
423    fn try_to_cpi_handle_mut(&mut self) -> Result<CpiHandleMut<'_>, ProgramError> {
424        (**self).try_to_cpi_handle_mut()
425    }
426}
427
428impl ToCpiHandle for CpiHandle<'_> {
429    #[inline(always)]
430    fn to_cpi_handle(&self) -> CpiHandle<'_> {
431        *self
432    }
433}
434
435impl ToCpiHandle for CpiHandleMut<'_> {
436    #[inline(always)]
437    fn to_cpi_handle(&self) -> CpiHandle<'_> {
438        (*self).into()
439    }
440}
441
442impl ToCpiHandleMut for CpiHandleMut<'_> {
443    #[inline(always)]
444    fn try_to_cpi_handle_mut(&mut self) -> Result<CpiHandleMut<'_>, ProgramError> {
445        Ok(*self)
446    }
447}
448
449impl ToCpiHandle for AccountView {
450    #[inline(always)]
451    fn to_cpi_handle(&self) -> CpiHandle<'_> {
452        CpiHandle::readonly(self)
453    }
454}
455
456impl ToCpiHandleMut for AccountView {
457    #[inline(always)]
458    fn try_to_cpi_handle_mut(&mut self) -> Result<CpiHandleMut<'_>, ProgramError> {
459        require!(self.is_writable(), ProgramError::InvalidArgument);
460        Ok(CpiHandleMut::writable(self))
461    }
462}
463
464/// Account-like value that can provide its on-chain address.
465///
466/// This is intentionally implemented blanketly for every [`AnchorAccount`]:
467/// `AnchorAccount::account()` already exposes the underlying `AccountView`,
468/// so boxed and typed account wrappers can all be used uniformly as address
469/// field references in generated constraint code.
470pub trait AccountAddress {
471    fn account_address(&self) -> &Address;
472}
473
474impl<T: AnchorAccount> AccountAddress for T {
475    #[inline(always)]
476    fn account_address(&self) -> &Address {
477        self.account().address()
478    }
479}
480
481impl<T: AccountAddress> AccountAddress for Option<T> {
482    #[inline(always)]
483    fn account_address(&self) -> &Address {
484        self.as_ref()
485            .expect("optional account is None")
486            .account_address()
487    }
488}
489
490/// v1-compatible utility methods for raw remaining-account views.
491#[cfg(feature = "compat")]
492pub trait AccountViewCompat {
493    fn key(&self) -> crate::solana_program::pubkey::Pubkey;
494
495    fn data_is_empty(&self) -> bool;
496
497    fn try_data_len(&self) -> Result<usize, ProgramError>;
498
499    fn try_borrow_data(&self) -> Result<Ref<'_, [u8]>, ProgramError>;
500
501    fn try_borrow_mut_data(&mut self) -> Result<RefMut<'_, [u8]>, ProgramError>;
502}
503
504#[cfg(feature = "compat")]
505impl AccountViewCompat for AccountView {
506    #[inline(always)]
507    fn key(&self) -> crate::solana_program::pubkey::Pubkey {
508        *self.address()
509    }
510
511    #[inline(always)]
512    fn data_is_empty(&self) -> bool {
513        self.data_len() == 0
514    }
515
516    #[inline(always)]
517    fn try_data_len(&self) -> Result<usize, ProgramError> {
518        Ok(self.data_len())
519    }
520
521    #[inline(always)]
522    fn try_borrow_data(&self) -> Result<Ref<'_, [u8]>, ProgramError> {
523        self.try_borrow()
524    }
525
526    #[inline(always)]
527    fn try_borrow_mut_data(&mut self) -> Result<RefMut<'_, [u8]>, ProgramError> {
528        self.try_borrow_mut()
529    }
530}
531
532/// Lamports related utility methods for accounts.
533pub trait Lamports: AsRef<AccountView> {
534    /// Get the lamports of the account.
535    #[inline(always)]
536    fn get_lamports(&self) -> u64 {
537        self.as_ref().lamports()
538    }
539
540    /// Add lamports to the account.
541    ///
542    /// This method is useful for transferring lamports from a PDA.
543    ///
544    /// # Requirements
545    ///
546    /// 1. The account must be marked `mut`.
547    /// 2. The total lamports before the transaction must equal the total
548    ///    lamports after the transaction.
549    ///
550    /// See [`Lamports::sub_lamports`] for subtracting lamports.
551    #[inline(always)]
552    fn add_lamports(&self, amount: u64) -> Result<&Self, ProgramError> {
553        let mut view = *self.as_ref();
554        view.set_lamports(
555            self.get_lamports()
556                .checked_add(amount)
557                .ok_or(ProgramError::ArithmeticOverflow)?,
558        );
559        Ok(self)
560    }
561
562    /// Subtract lamports from the account.
563    ///
564    /// This method is useful for transferring lamports from a PDA.
565    ///
566    /// # Requirements
567    ///
568    /// 1. The account must be owned by the executing program.
569    /// 2. The account must be marked `mut`.
570    /// 3. The total lamports before the transaction must equal the total
571    ///    lamports after the transaction.
572    ///
573    /// See [`Lamports::add_lamports`] for adding lamports.
574    #[inline(always)]
575    fn sub_lamports(&self, amount: u64) -> Result<&Self, ProgramError> {
576        let mut view = *self.as_ref();
577        view.set_lamports(
578            self.get_lamports()
579                .checked_sub(amount)
580                .ok_or(ProgramError::ArithmeticOverflow)?,
581        );
582        Ok(self)
583    }
584}
585
586impl<T: AsRef<AccountView>> Lamports for T {}
587
588/// Declares which program owns accounts of this data type.
589///
590/// For your own program's types, `#[account]` generates this automatically
591/// from the program's declared ID.
592///
593/// External crates implement this with their program's address:
594/// ```ignore
595/// impl Owner for TokenAccountData {
596///     const OWNER: Address = Token::ID;
597/// }
598/// ```
599pub trait Owner {
600    const OWNER: Address;
601}
602
603/// Declares the on-chain address for a program marker type.
604///
605/// `Address` is re-exported from `pinocchio`, which itself re-exports
606/// `solana_address::Address`. That means built-in markers such as
607/// `Token::id()` and `System::id()` can be passed directly to modern Solana
608/// instruction APIs that use `Address` or compatibility aliases named
609/// `Pubkey`.
610pub trait Id {
611    fn id() -> Address;
612    /// Well-known base58 program address for IDL emission. Empty string
613    /// signals "no address to advertise in the IDL" — consumed by
614    /// `IdlAccountType::__IDL_ADDRESS` on `Program<T>` and converted to
615    /// `None` there.
616    const IDL_ADDRESS: &'static str = "";
617}
618
619/// Declares multiple valid on-chain addresses for an interface program marker.
620pub trait Ids {
621    fn ids() -> &'static [Address];
622}
623
624pub trait Discriminator {
625    const DISCRIMINATOR: &'static [u8];
626}
627
628/// Client-side account deserialization. Mirrors v1 anchor-lang's trait so
629/// `anchor-client` can fetch raw account bytes and decode them into the
630/// user's `#[account]` struct. Generated account impls expect `buf` to start
631/// at the full account bytes, including the reserved discriminator prefix. The
632/// `#[account]` macro emits two impl bodies:
633///
634///   - Borsh mode (`#[account(borsh)]`): check disc, run `BorshDeserialize`.
635///   - Pod mode (default): check disc, `bytemuck::pod_read_unaligned` on
636///     the post-disc bytes.
637///
638/// Not used by the on-chain account wrappers (`BorshAccount` / `Slab`),
639/// which read directly from `AccountView` borrows; this is purely the
640/// off-chain client helper.
641pub trait AccountDeserialize: Sized {
642    /// Verify the leading discriminator and decode. Generated impls perform
643    /// the discriminator check; the default forwards to
644    /// `try_deserialize_unchecked`.
645    fn try_deserialize(buf: &mut &[u8]) -> Result<Self, ProgramError> {
646        Self::try_deserialize_unchecked(buf)
647    }
648
649    /// Decode without verifying the discriminator. Generated account impls
650    /// still skip over the reserved discriminator region before decoding the
651    /// payload, but they do not check the prefix bytes. Used during
652    /// initialization when the bytes are zero or otherwise not yet stamped
653    /// with the disc.
654    fn try_deserialize_unchecked(buf: &mut &[u8]) -> Result<Self, ProgramError>;
655}
656
657/// Wrapper-level init: creates the on-chain account and returns a loaded
658/// `Self`. `Slab<H, T>` and `BorshAccount<T>` get this automatically;
659/// custom wrappers implement it directly.
660pub trait AccountInitialize: Sized {
661    type Params<'a>: Default;
662
663    fn create_and_initialize<'a>(
664        payer: &AccountView,
665        account: &AccountView,
666        space: usize,
667        owner: &Address,
668        params: &Self::Params<'a>,
669        signer_seeds: Option<&[&[u8]]>,
670        payer_signer_seeds: Option<&[&[u8]]>,
671    ) -> Result<Self, ProgramError>;
672}
673
674/// Marker for account wrappers that may be allocated with an explicit
675/// foreign owner through `#[account(init, owner = ...)]`.
676///
677/// Typed account wrappers intentionally do not implement this: their init
678/// paths stamp and load Anchor-owned data, so they must stay owned by the
679/// current program. `UncheckedAccount` is the escape hatch for allocating
680/// bytes that a foreign program will initialize or validate later.
681pub trait ForeignOwnerInit: AccountInitialize {}
682
683// ---------------------------------------------------------------------------
684// Extensible constraint system
685// ---------------------------------------------------------------------------
686
687/// Trait implemented by each constraint marker type for every account
688/// type it applies to. Each method defaults to `Ok(())`, so CHECK-only
689/// constraints only need to override `check`, INIT-only constraints
690/// only override `init`, etc.
691///
692/// # Lifecycle mapping
693///
694/// | `#[account(...)]` spelling                         | Methods called        |
695/// |----------------------------------------------------|-----------------------|
696/// | `ns::key = v` (non-init field)                     | `check`               |
697/// | `init, ns::key = v`                                | `init`                |
698/// | `init_if_needed, ns::key = v` (creating)           | `init`, then `check`  |
699/// | `init_if_needed, ns::key = v` (already exists)     | `check`               |
700/// | `update(ns::key = v)`                              | `update` (post-validation) |
701/// | Any of the above                                    | `exit` (exit phase)  |
702///
703/// There is deliberately **no blanket `impl<T: AccountConstraint<A>>
704/// AccountConstraint<Option<A>> for T`** mirroring the `Box<T>` forwarder
705/// in `accounts/boxed.rs`. Constraint calls on `Option<Field>` are emitted
706/// by the derive inline as `if let Some(ref inner) = self.maybe_x { …
707/// inline call … }` — they never dispatch through a blanket impl.
708///
709/// # Extending with third-party constraints
710///
711/// Any crate can define new constraint markers and implement
712/// `AccountConstraint<SomeAccount>` for them. The derive routes
713/// `ns::key = v`, `init`/`init_if_needed`-paired constraints, and the
714/// `update(...)` wrapper through the appropriate method.
715///
716/// ```ignore
717/// pub mod my_ns {
718///     use anchor_lang::AccountConstraint;
719///     use pinocchio::program_error::ProgramError;
720///
721///     pub struct MinBalanceConstraint;
722///
723///     impl AccountConstraint<MyAccount> for MinBalanceConstraint {
724///         type Value = u64;
725///         fn check(account: &MyAccount, min: &u64) -> Result<(), ProgramError> {
726///             if account.account().lamports() < *min {
727///                 return Err(ProgramError::InsufficientFunds);
728///             }
729///             Ok(())
730///         }
731///     }
732/// }
733///
734/// #[derive(Accounts)]
735/// pub struct MyInstruction {
736///     #[account(mut, my_ns::min_balance = 1_000_000)]
737///     pub data: MyAccount,
738/// }
739/// ```
740pub trait AccountConstraint<A> {
741    /// The expected value type for this constraint. This is the type of
742    /// the RHS expression in `#[account(namespace::key = <expr>)]`.
743    ///
744    /// Common choices:
745    /// - `Address` for address comparisons (default for most constraints)
746    /// - `AccountView` for constraints that need the full account view
747    /// - `u8` / `u64` for numeric constraints
748    type Value;
749
750    /// Creation hook. Invoked on `init` and on the create branch of
751    /// `init_if_needed` — whenever the account is being freshly
752    /// produced by this instruction — after `AccountInitialize::
753    /// create_and_initialize` has run. Mutable access so the
754    /// constraint can stamp additional state.
755    #[inline(always)]
756    fn init(_account: &mut A, _value: &Self::Value) -> core::result::Result<(), ProgramError> {
757        Ok(())
758    }
759
760    /// Runtime validation. Invoked on non-init fields and on the
761    /// already-exists branch of `init_if_needed`. Read-only.
762    #[inline(always)]
763    fn check(_account: &A, _value: &Self::Value) -> core::result::Result<(), ProgramError> {
764        Ok(())
765    }
766
767    /// Mutating hook. Invoked only when the constraint is written
768    /// inside an `update(...)` wrapper, e.g.
769    /// `#[account(update(my_ns::field = value))]`. Intended for
770    /// constraints that set / rewrite on-chain state rather than
771    /// validating it. Runs after `try_accounts` has finished all
772    /// account validations, but before the instruction handler.
773    #[inline(always)]
774    fn update(_account: &mut A, _value: &Self::Value) -> core::result::Result<(), ProgramError> {
775        Ok(())
776    }
777
778    /// Exit hook. Called during `AccountsExit::exit_accounts()` for
779    /// every constraint attached to the field, regardless of how the
780    /// field was introduced. Use for state that must be flushed on a
781    /// successful instruction.
782    #[inline(always)]
783    fn exit(_account: &mut A, _value: &Self::Value) -> core::result::Result<(), ProgramError> {
784        Ok(())
785    }
786}
787
788pub struct Nested<T>(pub T);
789
790impl<T> Deref for Nested<T> {
791    type Target = T;
792    fn deref(&self) -> &T {
793        &self.0
794    }
795}
796
797impl<T> core::ops::DerefMut for Nested<T> {
798    fn deref_mut(&mut self) -> &mut T {
799        &mut self.0
800    }
801}
802
803#[doc(hidden)]
804impl<T: crate::IdlAccountType> crate::IdlAccountType for Nested<T> {
805    const __IDL_ACCOUNT_ENTRY: Option<&'static str> = T::__IDL_ACCOUNT_ENTRY;
806    const __IDL_TYPE_DEF: Option<&'static str> = T::__IDL_TYPE_DEF;
807    fn __idl_account_entry() -> Option<&'static str> {
808        T::__idl_account_entry()
809    }
810    fn __idl_type_def() -> Option<&'static str> {
811        T::__idl_type_def()
812    }
813    fn __register_idl_deps(
814        accounts: &mut ::alloc::vec::Vec<&'static str>,
815        types: &mut ::alloc::vec::Vec<&'static str>,
816    ) {
817        T::__register_idl_deps(accounts, types);
818    }
819}