use {
crate::{AccountSharedData, ReadableAccount, traits::debug_fmt},
solana_account_info::AccountInfo,
solana_clock::Epoch,
solana_pubkey::Pubkey,
solana_sdk_ids::{
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, loader_v4, native_loader,
},
std::{cell::RefCell, fmt, rc::Rc},
};
#[repr(C)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "wincode", derive(wincode::SchemaRead, wincode::SchemaWrite))]
#[derive(PartialEq, Eq, Clone, Default)]
pub struct Account {
pub lamports: u64,
#[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
pub data: Vec<u8>,
pub owner: Pubkey,
pub executable: bool,
pub rent_epoch: Epoch,
}
#[cfg(feature = "serde")]
mod account_serialize {
use {
crate::ReadableAccount,
serde::{Serialize, ser::Serializer},
solana_clock::Epoch,
solana_pubkey::Pubkey,
};
#[repr(C)]
#[derive(serde::Serialize)]
#[serde(rename_all = "camelCase")]
struct Account<'a> {
lamports: u64,
#[serde(with = "serde_bytes")]
data: &'a [u8],
owner: &'a Pubkey,
executable: bool,
rent_epoch: Epoch,
}
pub(crate) fn serialize_account<S>(
account: &impl ReadableAccount,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let account = Account {
lamports: account.lamports(),
data: account.data(),
owner: account.owner(),
executable: account.executable(),
rent_epoch: account.rent_epoch(),
};
account.serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl serde::ser::Serialize for Account {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
account_serialize::serialize_account(self, serializer)
}
}
#[cfg(feature = "serde")]
impl serde::ser::Serialize for AccountSharedData {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
account_serialize::serialize_account(self, serializer)
}
}
impl From<AccountSharedData> for Account {
fn from(other: AccountSharedData) -> Self {
Self {
lamports: other.lamports(),
data: other.data().to_vec(),
owner: *other.owner(),
executable: other.executable(),
rent_epoch: other.rent_epoch(),
}
}
}
impl fmt::Debug for Account {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
debug_fmt(self, f, |_| {})
}
}
impl fmt::Debug for AccountSharedData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
debug_fmt(self, f, |f| {
f.field("slot", &self.slot())
.field("mode", &self.mode)
.field("flags", self.flags())
.field("dirty", self.markers());
})
}
}
impl Account {
fn from_parts(
lamports: u64,
data: Vec<u8>,
owner: Pubkey,
executable: bool,
rent_epoch: Epoch,
) -> Self {
Self {
lamports,
data,
owner,
executable,
rent_epoch,
}
}
pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Self {
Self::new_rent_epoch(lamports, space, owner, Epoch::default())
}
pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self::new(lamports, space, owner)))
}
#[cfg(feature = "bincode")]
pub fn new_data<T: serde::Serialize>(
lamports: u64,
state: &T,
owner: &Pubkey,
) -> Result<Self, bincode::Error> {
let data = bincode::serialize(state)?;
Ok(Self::from_parts(
lamports,
data,
*owner,
false,
Epoch::default(),
))
}
#[cfg(feature = "bincode")]
pub fn new_ref_data<T: serde::Serialize>(
lamports: u64,
state: &T,
owner: &Pubkey,
) -> Result<RefCell<Self>, bincode::Error> {
Self::new_data(lamports, state, owner).map(RefCell::new)
}
#[cfg(feature = "bincode")]
pub fn new_data_with_space<T: serde::Serialize>(
lamports: u64,
state: &T,
space: usize,
owner: &Pubkey,
) -> Result<Self, bincode::Error> {
let mut account = Self::new(lamports, space, owner);
crate::codec::serialize_data(&mut account, state)?;
Ok(account)
}
#[cfg(feature = "bincode")]
pub fn new_ref_data_with_space<T: serde::Serialize>(
lamports: u64,
state: &T,
space: usize,
owner: &Pubkey,
) -> Result<RefCell<Self>, bincode::Error> {
Self::new_data_with_space(lamports, state, space, owner).map(RefCell::new)
}
pub fn new_rent_epoch(lamports: u64, space: usize, owner: &Pubkey, rent_epoch: Epoch) -> Self {
Self::from_parts(lamports, vec![0; space], *owner, false, rent_epoch)
}
#[cfg(feature = "bincode")]
pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
crate::codec::deserialize_data(self)
}
#[cfg(feature = "bincode")]
pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
crate::codec::serialize_data(self, state)
}
}
impl solana_account_info::Account for Account {
fn get(&mut self) -> (&mut u64, &mut [u8], &Pubkey, bool) {
(
&mut self.lamports,
&mut self.data,
&self.owner,
self.executable,
)
}
}
pub fn create_is_signer_account_infos<'a>(
accounts: &'a mut [(&'a Pubkey, bool, &'a mut Account)],
) -> Vec<AccountInfo<'a>> {
accounts
.iter_mut()
.map(|(key, is_signer, account)| {
AccountInfo::new(
key,
*is_signer,
false,
&mut account.lamports,
&mut account.data,
&account.owner,
account.executable,
)
})
.collect()
}
pub const PROGRAM_OWNERS: &[Pubkey] = &[
native_loader::id(),
bpf_loader_upgradeable::id(),
bpf_loader::id(),
bpf_loader_deprecated::id(),
loader_v4::id(),
];