1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
//! Tiered loading helpers for account views.
//!
//! The [`zero_copy_layout!`](crate::zero_copy_layout!) macro generates per-struct tiered loading
//! methods. This module provides the shared validation functions they
//! call.
//!
//! ## Trust Tiers
//!
//! | Tier | Name | Method | Validation | Use When |
//! |------|------|--------|------------|----------|
//! | 1 | **Verified** | `load()` / `load_mut()` | owner + disc + version + layout_id + exact size | Loading your own program's accounts |
//! | 2 | **Foreign Verified** | `load_foreign()` | owner + layout_id + exact size | Reading another program's accounts (cross-program) |
//! | 3 | **Compatibility** | `validate_version_compatible()` | owner + disc + version + min size (no layout_id) | Version migration, explicitly weaker |
//! | 4 | **Unsafe** | `load_unchecked()` | none (`unsafe`) | Hot path; caller assumes all risk |
//! | 5 | **Unverified Overlay** | `load_unverified_overlay()` | header + layout_id if present, fallback to overlay | Indexers, explorers, diagnostic tooling |
//!
//! Tiers 1–2 are the standard paths. Tier 3 is a migration helper that
//! trades `layout_id` verification for version-range flexibility. Tier 4
//! is `unsafe` by design - deliberate friction for unvalidated loads.
//! Tier 5 is for tooling that cannot guarantee account provenance.
//!
//! See [`SAFETY_MODEL.md`](https://github.com/QuarksBlueFoot/jiminy/blob/main/docs/SAFETY_MODEL.md)
//! for the full trust tier model and all safety invariants.
use ;
use ProgramError;
use ;
/// Validate owner + disc + version + layout_id + exact size on an `AccountView`.
///
/// This is the standard loading path (Tier 1). Returns the borrowed
/// account data on success, avoiding a second `try_borrow()` call.
///
/// # Errors
///
/// - `IllegalOwner`: account is not owned by `program_id`.
/// - `AccountDataTooSmall`: account data does not match `expected_size`.
/// - `InvalidAccountData`: discriminator, version, or layout_id mismatch.
/// Validate owner + layout_id + exact size on an `AccountView`.
///
/// Cross-program read path (Tier 2). Skips disc and version checks
/// because the foreign program may use different disc/version conventions.
/// Returns the borrowed account data on success.
///
/// # Errors
///
/// - `IllegalOwner`: account is not owned by `expected_owner`.
/// - `AccountDataTooSmall`: account data does not match `expected_size`.
/// - `InvalidAccountData`: `layout_id` does not match.
/// **Tier 2: Cross-program read for segmented accounts.**
///
/// Same as [`validate_foreign`] but uses minimum-size checking
/// instead of exact-size. Segmented accounts have variable length
/// depending on capacity, so exact-size matching is not possible.
///
/// Checks:
/// - Owner matches `expected_owner`
/// - Data length ≥ `min_size` (fixed prefix + segment table)
/// - `layout_id` matches (uses `SEGMENTED_LAYOUT_ID`)
///
/// # Errors
///
/// - `IllegalOwner`: account is not owned by `expected_owner`.
/// - `AccountDataTooSmall`: account data is smaller than `min_size`.
/// - `InvalidAccountData`: `layout_id` does not match.
/// Mutable variant of [`validate_account`] (Tier 1).
///
/// Same checks as `validate_account` but returns `RefMut` for write access.
/// Validate owner + disc + minimum version + minimum size.
///
/// # ⚠ Migration utility - lower trust level
///
/// **Compatibility validation is a migration helper, not a proof of ABI
/// identity.** It does not validate `layout_id` and must not be treated
/// as equivalent to `load()` or `load_foreign()`. It checks only that
/// the account is owned by the expected program, has the correct
/// discriminator, meets a minimum version, and is large enough.
///
/// Because the layout fingerprint is not verified, the caller must
/// ensure the overlaid struct is compatible with the actual on-chain
/// bytes. A `validate_version_compatible` call passing does **not** prove the
/// account's byte layout matches your Rust struct.
///
/// Use this only for backward-compatible loading during version
/// transitions. For all other paths, prefer:
///
/// - `load()` / `load_checked()`: full ABI-verified standard path
/// - `load_foreign()`: cross-program reads with layout_id proof
///
/// # Disabled in `strict` mode
///
/// When the `strict` feature is enabled this function is unavailable,
/// forcing all loads through layout_id-verified tiers.
///
/// # Errors
///
/// - `IllegalOwner`: account is not owned by `program_id`.
/// - `AccountDataTooSmall`: data shorter than `min_size` or shorter
/// than 2 bytes (cannot read disc + version).
/// - `InvalidAccountData`: discriminator does not match `disc`, or
/// version byte is less than `min_version`.
/// Try to validate header + layout_id. If the header check fails,
/// fall back to a plain overlay.
///
/// Unverified overlay loading (Tier 5). Useful for indexers and tooling
/// that need to read accounts without knowing whether they use Jiminy
/// headers. Returns `(overlay, validated)` where `validated` is `true`
/// when the header matched.
///
/// No ABI guarantees. The overlay is applied regardless of whether the
/// header validation succeeds. Use this only for diagnostic/tooling
/// purposes, never in on-chain program logic.
///
/// # Errors
///
/// - `AccountDataTooSmall`: data shorter than `T::SIZE`.