1#![allow(unsafe_op_in_unsafe_fn)]
5
6mod borrowed;
7mod owned;
8
9pub use borrowed::BorrowedAccount;
10pub use owned::{AccountBuilder, OwnedAccount};
11
12use crate::{Account, ReadableAccount, WritableAccount, patch::AccountPatchError};
13use solana_clock::{Epoch, Slot};
14use solana_pubkey::Pubkey;
15use std::{
16 cell::RefCell,
17 ops::{Deref, DerefMut},
18 rc::Rc,
19 sync::Arc,
20};
21
22use CoWAccount::*;
23
24pub const ALIGNMENT: usize = 8;
26pub const STORAGE_UNIT: usize = size_of::<StorageUnit>();
28#[repr(C)]
30#[derive(Clone, Copy, Default)]
31pub struct StorageUnit(pub u64);
32
33#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(from = "Account"))]
38#[derive(Clone, Default)]
39pub struct AccountSharedData {
40 pub(crate) cow: CoWAccount,
42 pub(crate) dirty: DirtyMarkers,
44}
45
46#[repr(C)]
48#[derive(Clone, Copy, Default, Eq, PartialEq)]
49#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
50pub struct AccountCore {
51 pub(crate) lamports: u64,
53 pub(crate) owner: Pubkey,
55 pub(crate) slot: Slot,
57 pub(crate) mode: AccountMode,
59 pub(crate) flags: StateFlags,
61 _padding: [u8; 6],
63}
64
65impl Deref for AccountSharedData {
66 type Target = AccountCore;
67
68 fn deref(&self) -> &Self::Target {
69 match &self.cow {
70 Borrowed(account) => {
71 unsafe { account.core.as_ref() }
74 }
75 Owned(account) => &account.core,
76 }
77 }
78}
79
80impl DerefMut for AccountSharedData {
81 fn deref_mut(&mut self) -> &mut Self::Target {
82 match &mut self.cow {
83 Borrowed(account) => {
84 unsafe { account.core.as_mut() }
86 }
87 Owned(account) => &mut account.core,
88 }
89 }
90}
91
92impl PartialEq for AccountSharedData {
93 fn eq(&self, other: &Self) -> bool {
94 self.deref() == other.deref() && self.cow.data() == other.cow.data()
95 }
96}
97
98impl Eq for AccountSharedData {}
99
100impl PartialEq<OwnedAccount> for AccountSharedData {
101 fn eq(&self, other: &OwnedAccount) -> bool {
102 self.deref() == &other.core && self.cow.data() == other.data.as_slice()
103 }
104}
105
106impl AccountSharedData {
107 pub fn cow(&self) -> &CoWAccount {
109 &self.cow
110 }
111
112 pub fn cow_mut(&mut self) -> &mut CoWAccount {
114 &mut self.cow
115 }
116
117 pub fn slot(&self) -> Slot {
119 self.slot
120 }
121
122 pub fn translate(&mut self) {
124 if self.dirty() {
125 return;
126 }
127 if let Borrowed(ref mut acc) = self.cow {
128 unsafe { acc.translate() };
131 }
132 }
133
134 pub fn owned(&self) -> OwnedAccount {
136 match self.cow() {
137 Borrowed(a) => a.into(),
138 Owned(a) => a.clone(),
139 }
140 }
141
142 pub fn mutable(&self) -> bool {
149 self.mode.mutable()
150 || matches!(self.mode, AccountMode::Transient | AccountMode::Closed)
151 && self.dirty.contains(DirtyMarkers::MODE)
152 }
153
154 pub fn mode(&self) -> AccountMode {
156 self.mode
157 }
158
159 pub fn is(&self, mode: AccountMode) -> bool {
161 self.mode == mode
162 }
163
164 pub fn flags(&self) -> &StateFlags {
166 &self.flags
167 }
168
169 pub fn markers(&self) -> &DirtyMarkers {
171 &self.dirty
172 }
173
174 pub(crate) fn mark_data_dirty(&mut self) {
176 self.dirty.insert(DirtyMarkers::DATA);
177 }
178
179 pub fn is_shared(&self) -> bool {
181 self.cow.is_shared()
182 }
183
184 pub fn dirty(&self) -> bool {
186 self.dirty.intersects(DirtyMarkers::all())
187 }
188
189 pub fn capacity(&self) -> usize {
191 self.cow.capacity()
192 }
193
194 pub fn data_clone(&self) -> Arc<Vec<u8>> {
196 self.cow.data_clone()
197 }
198
199 pub fn resize(&mut self, len: usize, val: u8) {
201 self.translate();
202 self.mark_data_dirty();
203 self.cow.resize(len, val);
204 }
205
206 pub fn extend_from_slice(&mut self, data: &[u8]) {
208 self.translate();
209 self.mark_data_dirty();
210 self.cow.extend_from_slice(data);
211 }
212
213 pub fn set_data_from_slice(&mut self, data: &[u8]) {
215 self.translate();
216 self.mark_data_dirty();
217 self.cow.set_data_from_slice(data);
218 }
219
220 pub fn set_lifecycle(
227 &mut self,
228 mode: AccountMode,
229 slot: Slot,
230 ) -> Result<(), AccountPatchError> {
231 self.mode.validate_transition(mode, self.slot, slot)?;
232 self.translate();
233 if self.mode != mode {
234 self.dirty.insert(DirtyMarkers::MODE);
235 self.mode = mode;
236 }
237 self.dirty.insert(DirtyMarkers::SLOT);
238 self.slot = slot;
239 Ok(())
240 }
241
242 pub(crate) fn set_data_at(&mut self, offset: usize, data: &[u8]) {
244 self.translate();
245 self.mark_data_dirty();
246 let len = self.data().len();
247 if offset > len {
248 self.resize(offset, 0);
251 }
252
253 let n = self.data().len().saturating_sub(offset).min(data.len());
256 self.data_as_mut_slice()[offset..offset + n].copy_from_slice(&data[..n]);
257 self.extend_from_slice(&data[n..]);
258 }
259
260 pub fn set_flags(&mut self, flags: StateFlags) {
262 if self.flags == flags {
263 return;
264 }
265 self.translate();
266 self.dirty.set(DirtyMarkers::FLAGS, true);
267 self.flags = flags;
268 }
269
270 pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Self {
272 AccountBuilder::default()
273 .lamports(lamports)
274 .data(vec![0; space])
275 .owner(*owner)
276 .build()
277 }
278 pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
280 Rc::new(RefCell::new(Self::new(lamports, space, owner)))
281 }
282
283 #[cfg(feature = "bincode")]
285 pub fn new_data<T: serde::Serialize>(
286 lamports: u64,
287 state: &T,
288 owner: &Pubkey,
289 ) -> Result<Self, bincode::Error> {
290 let data = bincode::serialize(state)?;
291 Ok(Self::create_from_existing_shared_data(
292 lamports,
293 Arc::new(data),
294 *owner,
295 false,
296 Epoch::default(),
297 ))
298 }
299
300 #[cfg(feature = "bincode")]
302 pub fn new_ref_data<T: serde::Serialize>(
303 lamports: u64,
304 state: &T,
305 owner: &Pubkey,
306 ) -> Result<RefCell<Self>, bincode::Error> {
307 Self::new_data(lamports, state, owner).map(RefCell::new)
308 }
309
310 #[cfg(feature = "bincode")]
312 pub fn new_data_with_space<T: serde::Serialize>(
313 lamports: u64,
314 state: &T,
315 space: usize,
316 owner: &Pubkey,
317 ) -> Result<Self, bincode::Error> {
318 let mut account = Self::new(lamports, space, owner);
319 crate::codec::serialize_data(&mut account, state)?;
320 Ok(account)
321 }
322
323 #[cfg(feature = "bincode")]
325 pub fn new_ref_data_with_space<T: serde::Serialize>(
326 lamports: u64,
327 state: &T,
328 space: usize,
329 owner: &Pubkey,
330 ) -> Result<RefCell<Self>, bincode::Error> {
331 Self::new_data_with_space(lamports, state, space, owner).map(RefCell::new)
332 }
333
334 pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, _: Epoch) -> Self {
338 Self::new(lamports, space, owner)
339 }
340
341 #[cfg(feature = "bincode")]
343 pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
344 crate::codec::deserialize_data(self)
345 }
346
347 #[cfg(feature = "bincode")]
349 pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
350 crate::codec::serialize_data(self, state)
351 }
352
353 pub fn create_from_existing_shared_data(
357 lamports: u64,
358 data: Arc<Vec<u8>>,
359 owner: Pubkey,
360 executable: bool,
361 _: Epoch,
362 ) -> Self {
363 AccountBuilder::default()
364 .lamports(lamports)
365 .data(data)
366 .owner(owner)
367 .executable(executable)
368 .build()
369 }
370}
371
372bitflags::bitflags! {
373 #[derive(Clone, Copy, Default, PartialEq, Eq, Debug)]
375 #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
376 pub struct StateFlags: u8 {
377 const EXECUTABLE = 1 << 0;
379 }
380
381 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
383 pub struct DirtyMarkers: u8 {
384 const OWNER = 1 << 0;
386 const LAMPORTS = 1 << 1;
388 const MODE = 1 << 2;
390 const FLAGS = 1 << 3;
392 const SLOT = 1 << 4;
394 const DATA = 1 << 5;
396 }
397}
398
399#[cfg(feature = "wincode")]
403const _: () = {
404 use core::mem::MaybeUninit;
405 use wincode::{
406 ReadError, ReadResult, SchemaRead, SchemaWrite, TypeMeta, WriteError, WriteResult,
407 config::ConfigCore,
408 io::{Reader, Writer},
409 };
410
411 unsafe impl<C: ConfigCore> SchemaWrite<C> for StateFlags {
413 type Src = StateFlags;
414 const TYPE_META: TypeMeta = TypeMeta::Static { size: 1, zero_copy: false };
415
416 fn size_of(_: &Self::Src) -> WriteResult<usize> {
417 Ok(1)
418 }
419
420 fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
421 let bytes = bincode::serialize(src).map_err(|_| WriteError::Custom("StateFlags"))?;
422 writer.write(&bytes)?;
423 Ok(())
424 }
425 }
426
427 unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for StateFlags {
429 type Dst = StateFlags;
430 const TYPE_META: TypeMeta = TypeMeta::Static { size: 1, zero_copy: false };
431
432 fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
433 let bytes = reader.take_array::<1>()?;
434 dst.write(bincode::deserialize(&bytes).map_err(|_| ReadError::Custom("StateFlags"))?);
435 Ok(())
436 }
437 }
438};
439
440#[derive(PartialEq, Eq)]
442pub enum CoWAccount {
443 Borrowed(BorrowedAccount),
445 Owned(OwnedAccount),
447}
448
449impl Clone for CoWAccount {
450 fn clone(&self) -> Self {
451 match self {
452 Borrowed(acc) => Self::Owned(acc.into()),
453 Owned(acc) => Self::Owned(acc.clone()),
454 }
455 }
456}
457
458impl CoWAccount {
459 pub(crate) fn promote(&mut self) {
461 let Self::Borrowed(account) = self else {
462 return;
463 };
464 *self = Self::Owned(account.deref().into());
465 }
466
467 pub(crate) fn data(&self) -> &[u8] {
469 match self {
470 Self::Borrowed(account) => &account.data,
471 Self::Owned(account) => &account.data,
472 }
473 }
474
475 pub(crate) fn is_shared(&self) -> bool {
477 match self {
478 Self::Borrowed(_) => false,
479 Self::Owned(account) => Arc::strong_count(&account.data) > 1,
480 }
481 }
482
483 pub(crate) fn capacity(&self) -> usize {
485 match self {
486 Self::Borrowed(account) => account.data.capacity(),
487 Self::Owned(account) => account.data.capacity(),
488 }
489 }
490
491 pub(crate) fn data_clone(&self) -> Arc<Vec<u8>> {
493 match self {
494 Self::Borrowed(account) => Arc::new(account.data.to_vec()),
495 Self::Owned(account) => Arc::clone(&account.data),
496 }
497 }
498
499 pub(crate) fn data_mut(&mut self) -> &mut [u8] {
501 match self {
502 Self::Borrowed(account) => &mut account.data,
503 Self::Owned(account) => Arc::<Vec<u8>>::make_mut(&mut account.data).as_mut_slice(),
504 }
505 }
506
507 pub fn reserve(&mut self, additional: usize) {
509 if let Self::Borrowed(a) = self
510 && a.data.spare() >= additional
511 {
512 return;
513 }
514 self.promote();
515 if let Self::Owned(account) = self {
516 Arc::make_mut(&mut account.data).reserve(additional);
517 }
518 }
519
520 pub(crate) fn resize(&mut self, len: usize, val: u8) {
522 if let Self::Borrowed(a) = self
523 && len <= a.data.capacity()
524 {
525 unsafe { a.data.resize(len, val) };
528 return;
529 }
530
531 self.promote();
532 if let Self::Owned(account) = self {
533 Arc::make_mut(&mut account.data).resize(len, val);
534 }
535 }
536
537 pub(crate) fn extend_from_slice(&mut self, data: &[u8]) {
539 self.reserve(data.len());
540
541 match self {
542 Self::Borrowed(account) => {
543 unsafe { account.data.extend(data) };
546 }
547 Self::Owned(account) => Arc::make_mut(&mut account.data).extend_from_slice(data),
548 }
549 }
550
551 pub(crate) fn set_data_from_slice(&mut self, data: &[u8]) {
553 let additional = data.len().saturating_sub(self.data().len());
554 self.reserve(additional);
555
556 match self {
557 Self::Borrowed(account) => {
558 unsafe { account.data.set(data) };
561 }
562 Self::Owned(account) => {
563 let data_buf = Arc::make_mut(&mut account.data);
564 data_buf.clear();
565 data_buf.extend_from_slice(data);
566 }
567 }
568 }
569}
570
571#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
573#[repr(u8)]
574#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
575#[cfg_attr(feature = "wincode", derive(wincode::SchemaRead, wincode::SchemaWrite))]
576pub enum AccountMode {
577 #[default]
579 Placeholder = 0,
580 ReadOnly,
582 System,
584 Delegated,
586 Ephemeral,
588 Transient,
590 Closed = 255,
592}
593
594impl AccountMode {
595 pub fn allows_transition(self, to: Self, from_slot: Slot, to_slot: Slot) -> bool {
601 self.validate_transition(to, from_slot, to_slot).is_ok()
602 }
603
604 fn validate_transition(
605 self,
606 to: Self,
607 from_slot: Slot,
608 to_slot: Slot,
609 ) -> Result<(), AccountPatchError> {
610 use AccountMode::*;
611 let valid_slot = match (self, to) {
612 (Placeholder, ReadOnly | System | Delegated | Ephemeral | Closed)
613 | (ReadOnly, Delegated | Ephemeral | Closed)
614 | (Delegated, Transient)
615 | (Transient, ReadOnly | Placeholder)
616 | (Ephemeral, Closed) => to_slot >= from_slot,
617 (Placeholder, Placeholder)
619 | (ReadOnly, ReadOnly | Placeholder)
620 | (System, System)
621 | (Transient, Delegated) => to_slot > from_slot,
622 _ => return Err(AccountPatchError::InvalidModeTransition { from: self, to }),
623 };
624 if !valid_slot {
625 return Err(AccountPatchError::InvalidSlotTransition { from: from_slot, to: to_slot });
626 }
627 Ok(())
628 }
629
630 pub fn mutable(&self) -> bool {
632 use AccountMode::*;
633 matches!(self, Delegated | Ephemeral)
634 }
635
636 pub fn authoritative(&self) -> bool {
638 use AccountMode::*;
639 matches!(self, Delegated | Ephemeral | Transient)
640 }
641}
642
643pub struct AccountSeqLock {
646 account: AccountSharedData,
647 sequence: Option<u32>,
648}
649
650impl AccountSeqLock {
651 pub fn new(account: AccountSharedData) -> Self {
653 let mut sequence = None;
654 if let Borrowed(ref acc) = account.cow {
655 sequence.replace(acc.version);
656 }
657 Self { account, sequence }
658 }
659
660 pub fn read<F, R>(&mut self, reader: F) -> R
666 where
667 F: Fn(&AccountSharedData) -> R,
668 {
669 loop {
670 let pre = self.sequence.unwrap_or_default();
672 let result = reader(&self.account);
673 match self.account.cow_mut() {
674 Borrowed(acc) => {
675 let post = acc.sequence();
676 if pre == post {
677 return result;
678 }
679 unsafe { acc.reset() };
682 self.sequence = Some(acc.version);
683 }
684 Owned(_) => return result,
685 }
686 }
687 }
688}
689
690impl Default for CoWAccount {
691 fn default() -> Self {
692 Self::Owned(OwnedAccount::default())
693 }
694}
695
696impl From<OwnedAccount> for AccountSharedData {
698 fn from(value: OwnedAccount) -> Self {
699 Self {
700 cow: Owned(value),
701 dirty: DirtyMarkers::default(),
702 }
703 }
704}
705
706impl From<BorrowedAccount> for AccountSharedData {
708 fn from(value: BorrowedAccount) -> Self {
709 Self {
710 cow: Borrowed(value),
711 dirty: DirtyMarkers::default(),
712 }
713 }
714}
715
716impl From<Account> for AccountSharedData {
718 fn from(value: Account) -> Self {
719 AccountBuilder::default()
720 .lamports(value.lamports)
721 .data(value.data)
722 .owner(value.owner)
723 .executable(value.executable)
724 .build()
725 }
726}
727
728unsafe impl Sync for AccountSharedData {}