Separate the "program" feature of solana-sdk into a new crate called solana-program (bp #12989) (#13131)

* Add solana-program-sdk boilerplate

(cherry picked from commit 3718771ffb)

# Conflicts:
#	sdk/Cargo.toml

* Initial population of solana-program-sdk

(cherry picked from commit 63db324204)

# Conflicts:
#	Cargo.lock

* Port programs to solana-program-sdk

(cherry picked from commit fe68f7f786)

# Conflicts:
#	programs/bpf/Cargo.lock
#	programs/bpf/rust/128bit/Cargo.toml
#	programs/bpf/rust/128bit_dep/Cargo.toml
#	programs/bpf/rust/alloc/Cargo.toml
#	programs/bpf/rust/call_depth/Cargo.toml
#	programs/bpf/rust/custom_heap/Cargo.toml
#	programs/bpf/rust/dep_crate/Cargo.toml
#	programs/bpf/rust/deprecated_loader/Cargo.toml
#	programs/bpf/rust/dup_accounts/Cargo.toml
#	programs/bpf/rust/error_handling/Cargo.toml
#	programs/bpf/rust/external_spend/Cargo.toml
#	programs/bpf/rust/instruction_introspection/Cargo.toml
#	programs/bpf/rust/invoke/Cargo.toml
#	programs/bpf/rust/invoked/Cargo.toml
#	programs/bpf/rust/iter/Cargo.toml
#	programs/bpf/rust/many_args/Cargo.toml
#	programs/bpf/rust/many_args_dep/Cargo.toml
#	programs/bpf/rust/noop/Cargo.toml
#	programs/bpf/rust/panic/Cargo.toml
#	programs/bpf/rust/param_passing/Cargo.toml
#	programs/bpf/rust/param_passing_dep/Cargo.toml
#	programs/bpf/rust/rand/Cargo.toml
#	programs/bpf/rust/ristretto/Cargo.toml
#	programs/bpf/rust/sanity/Cargo.toml
#	programs/bpf/rust/sha256/Cargo.toml
#	programs/bpf/rust/sysval/Cargo.toml

* Only activate legacy program feature for the solana-sdk crate

(cherry picked from commit 85c51f5787)

* Run serum-dex unit tests

(cherry picked from commit 92ce381d60)

* Rename solana-program-sdk to solana-program

(cherry picked from commit dd711ab5fb)

# Conflicts:
#	programs/bpf/rust/128bit/Cargo.toml
#	programs/bpf/rust/128bit_dep/Cargo.toml
#	programs/bpf/rust/alloc/Cargo.toml
#	programs/bpf/rust/call_depth/Cargo.toml
#	programs/bpf/rust/custom_heap/Cargo.toml
#	programs/bpf/rust/dep_crate/Cargo.toml
#	programs/bpf/rust/deprecated_loader/Cargo.toml
#	programs/bpf/rust/dup_accounts/Cargo.toml
#	programs/bpf/rust/error_handling/Cargo.toml
#	programs/bpf/rust/external_spend/Cargo.toml
#	programs/bpf/rust/instruction_introspection/Cargo.toml
#	programs/bpf/rust/invoke/Cargo.toml
#	programs/bpf/rust/invoked/Cargo.toml
#	programs/bpf/rust/iter/Cargo.toml
#	programs/bpf/rust/many_args/Cargo.toml
#	programs/bpf/rust/many_args_dep/Cargo.toml
#	programs/bpf/rust/noop/Cargo.toml
#	programs/bpf/rust/panic/Cargo.toml
#	programs/bpf/rust/param_passing/Cargo.toml
#	programs/bpf/rust/param_passing_dep/Cargo.toml
#	programs/bpf/rust/rand/Cargo.toml
#	programs/bpf/rust/ristretto/Cargo.toml
#	programs/bpf/rust/sanity/Cargo.toml
#	programs/bpf/rust/sha256/Cargo.toml
#	programs/bpf/rust/sysval/Cargo.toml

* Update frozen_abi hashes

The movement of files in sdk/ caused ABI hashes to change

(cherry picked from commit a4956844bd)

* Resolve merge conflicts

Co-authored-by: Michael Vines <mvines@gmail.com>
This commit is contained in:
mergify[bot]
2020-10-24 17:25:22 +00:00
committed by GitHub
parent 62e0e19961
commit eb9cef0cd4
143 changed files with 1616 additions and 1483 deletions

View File

@@ -1,302 +0,0 @@
use crate::{clock::Epoch, instruction::InstructionError, pubkey::Pubkey};
use std::{
cell::{Ref, RefCell, RefMut},
cmp, fmt,
iter::FromIterator,
rc::Rc,
};
/// An Account with data that is stored on chain
#[repr(C)]
#[frozen_abi(digest = "By9FhuLAM947tkLxbTVQru9ZKTrRQuvCR5W387nPSLNu")]
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Default, AbiExample)]
#[serde(rename_all = "camelCase")]
pub struct Account {
/// lamports in the account
pub lamports: u64,
/// data held in this account
#[serde(with = "serde_bytes")]
pub data: Vec<u8>,
/// the program that owns this account. If executable, the program that loads this account.
pub owner: Pubkey,
/// this account's data contains a loaded program (and is now read-only)
pub executable: bool,
/// the epoch at which this account will next owe rent
pub rent_epoch: Epoch,
}
impl fmt::Debug for Account {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let data_len = cmp::min(64, self.data.len());
let data_str = if data_len > 0 {
format!(" data: {}", hex::encode(self.data[..data_len].to_vec()))
} else {
"".to_string()
};
write!(
f,
"Account {{ lamports: {} data.len: {} owner: {} executable: {} rent_epoch: {}{} }}",
self.lamports,
self.data.len(),
self.owner,
self.executable,
self.rent_epoch,
data_str,
)
}
}
impl Account {
pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Self {
Self {
lamports,
data: vec![0u8; space],
owner: *owner,
..Self::default()
}
}
pub fn new_ref(lamports: u64, space: usize, owner: &Pubkey) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self::new(lamports, space, owner)))
}
pub fn new_data<T: serde::Serialize>(
lamports: u64,
state: &T,
owner: &Pubkey,
) -> Result<Self, bincode::Error> {
let data = bincode::serialize(state)?;
Ok(Self {
lamports,
data,
owner: *owner,
..Self::default()
})
}
pub fn new_ref_data<T: serde::Serialize>(
lamports: u64,
state: &T,
owner: &Pubkey,
) -> Result<RefCell<Self>, bincode::Error> {
Ok(RefCell::new(Self::new_data(lamports, state, owner)?))
}
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);
account.serialize_data(state)?;
Ok(account)
}
pub fn new_ref_data_with_space<T: serde::Serialize>(
lamports: u64,
state: &T,
space: usize,
owner: &Pubkey,
) -> Result<RefCell<Self>, bincode::Error> {
Ok(RefCell::new(Self::new_data_with_space(
lamports, state, space, owner,
)?))
}
pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
bincode::deserialize(&self.data)
}
pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
if bincode::serialized_size(state)? > self.data.len() as u64 {
return Err(Box::new(bincode::ErrorKind::SizeLimit));
}
bincode::serialize_into(&mut self.data[..], state)
}
}
#[repr(C)]
#[derive(Debug)]
pub struct KeyedAccount<'a> {
is_signer: bool, // Transaction was signed by this account's key
is_writable: bool,
key: &'a Pubkey,
pub account: &'a RefCell<Account>,
}
impl<'a> KeyedAccount<'a> {
pub fn signer_key(&self) -> Option<&Pubkey> {
if self.is_signer {
Some(self.key)
} else {
None
}
}
pub fn unsigned_key(&self) -> &Pubkey {
self.key
}
pub fn is_writable(&self) -> bool {
self.is_writable
}
pub fn lamports(&self) -> Result<u64, InstructionError> {
Ok(self.try_borrow()?.lamports)
}
pub fn data_len(&self) -> Result<usize, InstructionError> {
Ok(self.try_borrow()?.data.len())
}
pub fn data_is_empty(&self) -> Result<bool, InstructionError> {
Ok(self.try_borrow()?.data.is_empty())
}
pub fn owner(&self) -> Result<Pubkey, InstructionError> {
Ok(self.try_borrow()?.owner)
}
pub fn executable(&self) -> Result<bool, InstructionError> {
Ok(self.try_borrow()?.executable)
}
pub fn rent_epoch(&self) -> Result<Epoch, InstructionError> {
Ok(self.try_borrow()?.rent_epoch)
}
pub fn try_account_ref(&'a self) -> Result<Ref<Account>, InstructionError> {
self.try_borrow()
}
pub fn try_account_ref_mut(&'a self) -> Result<RefMut<Account>, InstructionError> {
self.try_borrow_mut()
}
fn try_borrow(&self) -> Result<Ref<Account>, InstructionError> {
self.account
.try_borrow()
.map_err(|_| InstructionError::AccountBorrowFailed)
}
fn try_borrow_mut(&self) -> Result<RefMut<Account>, InstructionError> {
self.account
.try_borrow_mut()
.map_err(|_| InstructionError::AccountBorrowFailed)
}
pub fn new(key: &'a Pubkey, is_signer: bool, account: &'a RefCell<Account>) -> Self {
Self {
is_signer,
is_writable: true,
key,
account,
}
}
pub fn new_readonly(key: &'a Pubkey, is_signer: bool, account: &'a RefCell<Account>) -> Self {
Self {
is_signer,
is_writable: false,
key,
account,
}
}
}
impl<'a> PartialEq for KeyedAccount<'a> {
fn eq(&self, other: &Self) -> bool {
self.key == other.key
}
}
impl<'a> From<(&'a Pubkey, &'a RefCell<Account>)> for KeyedAccount<'a> {
fn from((key, account): (&'a Pubkey, &'a RefCell<Account>)) -> Self {
Self {
is_signer: false,
is_writable: true,
key,
account,
}
}
}
impl<'a> From<(&'a Pubkey, bool, &'a RefCell<Account>)> for KeyedAccount<'a> {
fn from((key, is_signer, account): (&'a Pubkey, bool, &'a RefCell<Account>)) -> Self {
Self {
is_signer,
is_writable: true,
key,
account,
}
}
}
impl<'a> From<&'a (&'a Pubkey, &'a RefCell<Account>)> for KeyedAccount<'a> {
fn from((key, account): &'a (&'a Pubkey, &'a RefCell<Account>)) -> Self {
Self {
is_signer: false,
is_writable: true,
key,
account,
}
}
}
pub fn create_keyed_accounts<'a>(
accounts: &'a [(&'a Pubkey, &'a RefCell<Account>)],
) -> Vec<KeyedAccount<'a>> {
accounts.iter().map(Into::into).collect()
}
pub fn create_keyed_is_signer_accounts<'a>(
accounts: &'a [(&'a Pubkey, bool, &'a RefCell<Account>)],
) -> Vec<KeyedAccount<'a>> {
accounts
.iter()
.map(|(key, is_signer, account)| KeyedAccount {
is_signer: *is_signer,
is_writable: false,
key,
account,
})
.collect()
}
pub fn create_keyed_readonly_accounts(
accounts: &[(Pubkey, RefCell<Account>)],
) -> Vec<KeyedAccount> {
accounts
.iter()
.map(|(key, account)| KeyedAccount {
is_signer: false,
is_writable: false,
key,
account,
})
.collect()
}
/// Return all the signers from a set of KeyedAccounts
pub fn get_signers<A>(keyed_accounts: &[KeyedAccount]) -> A
where
A: FromIterator<Pubkey>,
{
keyed_accounts
.iter()
.filter_map(|keyed_account| keyed_account.signer_key())
.cloned()
.collect::<A>()
}
/// Return the next KeyedAccount or a NotEnoughAccountKeys error
pub fn next_keyed_account<'a, 'b, I: Iterator<Item = &'a KeyedAccount<'b>>>(
iter: &mut I,
) -> Result<I::Item, InstructionError> {
iter.next().ok_or(InstructionError::NotEnoughAccountKeys)
}
/// Return true if the first keyed_account is executable, used to determine if
/// the loader should call a program's 'main'
pub fn is_executable(keyed_accounts: &[KeyedAccount]) -> Result<bool, InstructionError> {
Ok(!keyed_accounts.is_empty() && keyed_accounts[0].executable()?)
}