Skip to content

Commit

Permalink
Add no std crate attribute (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
febo authored Sep 13, 2024
1 parent 3b6ce5a commit 1704c36
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 110 deletions.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[workspace]
resolver = "2"
members = ["sdk", "macro"]
members = [
"sdk",
"macro"
]
16 changes: 7 additions & 9 deletions sdk/src/account_info.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//! Data structures to represent account information.
#![allow(clippy::missing_safety_doc)]

use std::{ptr::NonNull, slice::from_raw_parts_mut};
use core::{ptr::NonNull, slice::from_raw_parts_mut};

use crate::{program_error::ProgramError, pubkey::Pubkey, syscalls::sol_memset_};

Expand Down Expand Up @@ -144,13 +142,13 @@ impl AccountInfo {
#[allow(invalid_reference_casting)]
pub fn assign(&self, new_owner: &Pubkey) {
unsafe {
std::ptr::write_volatile(&(*self.raw).owner as *const _ as *mut Pubkey, *new_owner);
core::ptr::write_volatile(&(*self.raw).owner as *const _ as *mut Pubkey, *new_owner);
}
}

/// Returns a read-only reference to the lamports in the account.
///
/// # SAFETY
/// # Safety
///
/// This does not check or modify the 4-bit refcell. Useful when instruction
/// has verified non-duplicate accounts.
Expand All @@ -160,7 +158,7 @@ impl AccountInfo {

/// Returns a mutable reference to the lamports in the account.
///
/// # SAFETY
/// # Safety
///
/// This does not check or modify the 4-bit refcell. Useful when instruction
/// has verified non-duplicate accounts.
Expand All @@ -171,7 +169,7 @@ impl AccountInfo {

/// Returns a read-only reference to the data in the account.
///
/// # SAFETY
/// # Safety
///
/// This does not check or modify the 4-bit refcell. Useful when instruction
/// has verified non-duplicate accounts.
Expand All @@ -181,7 +179,7 @@ impl AccountInfo {

/// Returns a mutable reference to the data in the account.
///
/// # SAFETY
/// # Safety
///
/// This does not check or modify the 4-bit refcell. Useful when instruction
/// has verified non-duplicate accounts.
Expand Down Expand Up @@ -353,7 +351,7 @@ impl AccountInfo {

/// Returns the memory address of the account data.
fn data_ptr(&self) -> *mut u8 {
unsafe { (self.raw as *const _ as *mut u8).add(std::mem::size_of::<Account>()) }
unsafe { (self.raw as *const _ as *mut u8).add(core::mem::size_of::<Account>()) }
}
}

Expand Down
107 changes: 56 additions & 51 deletions sdk/src/entrypoint.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{alloc::Layout, mem::size_of, ptr::null_mut, slice::from_raw_parts};
use core::{alloc::Layout, mem::size_of, ptr::null_mut, slice::from_raw_parts};

use crate::{
account_info::{Account, AccountInfo, MAX_PERMITTED_DATA_INCREASE},
Expand All @@ -23,7 +23,7 @@ pub const HEAP_LENGTH: usize = 32 * 1024;
/// [maximum number of accounts]: https://github.com/anza-xyz/agave/blob/2e6ca8c1f62db62c1db7f19c9962d4db43d0d550/runtime/src/bank.rs#L3209-L3221
pub const MAX_TX_ACCOUNTS: usize = 128;

/// `assert_eq(std::mem::align_of::<u128>(), 8)` is true for BPF but not
/// `assert_eq(core::mem::align_of::<u128>(), 8)` is true for BPF but not
/// for some host machines.
pub const BPF_ALIGN_OF_U128: usize = 8;

Expand Down Expand Up @@ -107,8 +107,8 @@ macro_rules! entrypoint {
( $process_instruction:ident, $maximum:expr ) => {
#[no_mangle]
pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 {
const UNINIT: std::mem::MaybeUninit<$crate::account_info::AccountInfo> =
std::mem::MaybeUninit::<$crate::account_info::AccountInfo>::uninit();
const UNINIT: core::mem::MaybeUninit<$crate::account_info::AccountInfo> =
core::mem::MaybeUninit::<$crate::account_info::AccountInfo>::uninit();
// create an array of uninitialized account infos; it is safe to `assume_init` since
// we are claiming that the array of `MaybeUninit` is initialized and `MaybeUninit` do
// not require initialization
Expand All @@ -121,7 +121,7 @@ macro_rules! entrypoint {
// they are initialized so we cast the pointer to a slice of `[AccountInfo]`
match $process_instruction(
&program_id,
std::slice::from_raw_parts(accounts.as_ptr() as _, count),
core::slice::from_raw_parts(accounts.as_ptr() as _, count),
&instruction_data,
) {
Ok(()) => $crate::entrypoint::SUCCESS,
Expand All @@ -142,76 +142,81 @@ macro_rules! entrypoint {
#[inline(always)]
pub unsafe fn deserialize<'a, const MAX_ACCOUNTS: usize>(
input: *mut u8,
accounts: &mut [std::mem::MaybeUninit<AccountInfo>],
accounts: &mut [core::mem::MaybeUninit<AccountInfo>],
) -> (&'a Pubkey, usize, &'a [u8]) {
let mut offset: usize = 0;

// total number of accounts present; it only process up to MAX_ACCOUNTS
let total_accounts = *(input.add(offset) as *const u64) as usize;
offset += core::mem::size_of::<u64>();

// number of processed accounts
let count = if total_accounts <= MAX_ACCOUNTS {
total_accounts
} else {
MAX_ACCOUNTS
};

offset += std::mem::size_of::<u64>();
let processed = if total_accounts > 0 {
// number of accounts to process (limited to MAX_ACCOUNTS)
let processed = if total_accounts > MAX_ACCOUNTS {
MAX_ACCOUNTS
} else {
total_accounts
};

for i in 0..count {
let duplicate_info = *(input.add(offset) as *const u8);
if duplicate_info == NON_DUP_MARKER {
let account_info: *mut Account = input.add(offset) as *mut _;
for i in 0..processed {
let duplicate_info = *(input.add(offset) as *const u8);
if duplicate_info == NON_DUP_MARKER {
let account_info: *mut Account = input.add(offset) as *mut _;

offset += std::mem::size_of::<Account>();
offset += (*account_info).data_len as usize;
offset += MAX_PERMITTED_DATA_INCREASE;
offset += (offset as *const u8).align_offset(BPF_ALIGN_OF_U128);
offset += std::mem::size_of::<u64>(); // MAGNETAR FIELDS: ignore rent epoch
offset += core::mem::size_of::<Account>();
offset += (*account_info).data_len as usize;
offset += MAX_PERMITTED_DATA_INCREASE;
offset += (offset as *const u8).align_offset(BPF_ALIGN_OF_U128);
offset += core::mem::size_of::<u64>();

// MAGNETAR FIELDS: reset borrow state right before pushing
(*account_info).borrow_state = 0b_0000_0000;
(*account_info).borrow_state = 0b_0000_0000;

accounts[i].write(AccountInfo {
raw: account_info as *const _ as *mut _,
});
} else {
offset += 8;
// duplicate account, clone the original pointer
accounts[i].write(accounts[duplicate_info as usize].assume_init_ref().clone());
accounts[i].write(AccountInfo {
raw: account_info as *const _ as *mut _,
});
} else {
offset += 8;
// duplicate account, clone the original pointer
accounts[i].write(accounts[duplicate_info as usize].assume_init_ref().clone());
}
}
}

// process any remaining accounts to move the offset to the instruction
// data (there is a duplication of logic but we avoid testing whether we
// have space for the account or not)
for _ in count..total_accounts {
let duplicate_info = *(input.add(offset) as *const u8);
// process any remaining accounts to move the offset to the instruction
// data (there is a duplication of logic but we avoid testing whether we
// have space for the account or not)
for _ in processed..total_accounts {
let duplicate_info = *(input.add(offset) as *const u8);

if duplicate_info == NON_DUP_MARKER {
let account_info: *mut Account = input.add(offset) as *mut _;
offset += std::mem::size_of::<Account>();
offset += (*account_info).data_len as usize;
offset += MAX_PERMITTED_DATA_INCREASE;
offset += (offset as *const u8).align_offset(BPF_ALIGN_OF_U128);
offset += std::mem::size_of::<u64>(); // MAGNETAR FIELDS: ignore rent epoch
} else {
offset += 8;
if duplicate_info == NON_DUP_MARKER {
let account_info: *mut Account = input.add(offset) as *mut _;
offset += core::mem::size_of::<Account>();
offset += (*account_info).data_len as usize;
offset += MAX_PERMITTED_DATA_INCREASE;
offset += (offset as *const u8).align_offset(BPF_ALIGN_OF_U128);
offset += core::mem::size_of::<u64>();
} else {
offset += 8;
}
}
}

processed
} else {
// no accounts to process
0
};

// instruction data
#[allow(clippy::cast_ptr_alignment)]
let instruction_data_len = *(input.add(offset) as *const u64) as usize;
offset += std::mem::size_of::<u64>();
offset += core::mem::size_of::<u64>();

let instruction_data = { from_raw_parts(input.add(offset), instruction_data_len) };
offset += instruction_data_len;

// program id
let program_id: &Pubkey = &*(input.add(offset) as *const Pubkey);

(program_id, count, instruction_data)
(program_id, processed, instruction_data)
}

#[macro_export]
Expand Down Expand Up @@ -248,7 +253,7 @@ pub struct BumpAllocator {
/// operating on the prescribed `HEAP_START_ADDRESS` and `HEAP_LENGTH`. Any
/// other use may overflow and is thus unsupported and at one's own risk.
#[allow(clippy::arithmetic_side_effects)]
unsafe impl std::alloc::GlobalAlloc for BumpAllocator {
unsafe impl core::alloc::GlobalAlloc for BumpAllocator {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let pos_ptr = self.start as *mut usize;
Expand Down
46 changes: 1 addition & 45 deletions sdk/src/instruction.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::marker::PhantomData;
use core::marker::PhantomData;

use crate::{account_info::AccountInfo, pubkey::Pubkey};

Expand All @@ -19,50 +19,6 @@ where
pub accounts: &'b [AccountMeta<'a>],
}

/*
/// An `Instruction` as expected by `sol_invoke_signed_c`.
#[repr(C)]
#[derive(Debug, PartialEq, Clone)]
pub struct Instruction<'a, 'b, 'c, 'd> {
/// Public key of the program.
program_id: &'c Pubkey,
/// Accounts expected by the program instruction.
accounts: *const AccountMeta<'a>,
/// Number of accounts expected by the program instruction.
accounts_len: u64,
/// Data expected by the program instruction.
data: *const u8,
/// Length of the data expected by the program instruction.
data_len: u64,
_accounts: PhantomData<&'b [AccountMeta<'a>]>,
_data: PhantomData<&'d [u8]>,
}
impl<'a, 'b, 'c, 'd> Instruction<'a, 'b, 'c, 'd> {
pub fn new(
program_id: &'c Pubkey,
accounts: &'b [AccountMeta<'a>],
instruction_data: &'d [u8],
) -> Self {
Self {
program_id,
accounts: accounts.as_ptr(),
accounts_len: accounts.len() as u64,
data: instruction_data.as_ptr(),
data_len: instruction_data.len() as u64,
_accounts: PhantomData::<&'b [AccountMeta<'a>]>,
_data: PhantomData::<&'d [u8]>,
}
}
}
*/

/// Use to query and convey information about the sibling instruction components
/// when calling the `sol_get_processed_sibling_instruction` syscall.
#[repr(C)]
Expand Down
5 changes: 5 additions & 0 deletions sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
//!
//! [`solana-sdk`]: https://docs.rs/solana-sdk/latest/solana_sdk/
//! [`solana-program`]: https://docs.rs/solana-program/latest/solana_program/
//!
#![no_std]

extern crate alloc;

pub mod account_info;
pub mod entrypoint;
Expand Down
8 changes: 4 additions & 4 deletions sdk/src/program_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ pub enum ProgramError {
/// Provided seeds do not result in a valid address
InvalidSeeds,

/// IO Error: `{0}`
BorshIoError(String),
/// IO Error
BorshIoError,

/// An account does not have enough lamports to be rent-exempt
AccountNotRentExempt,
Expand Down Expand Up @@ -147,7 +147,7 @@ impl From<u64> for ProgramError {
ACCOUNT_BORROW_FAILED => Self::AccountBorrowFailed,
MAX_SEED_LENGTH_EXCEEDED => Self::MaxSeedLengthExceeded,
INVALID_SEEDS => Self::InvalidSeeds,
BORSH_IO_ERROR => Self::BorshIoError("Unknown".to_string()),
BORSH_IO_ERROR => Self::BorshIoError,
ACCOUNT_NOT_RENT_EXEMPT => Self::AccountNotRentExempt,
UNSUPPORTED_SYSVAR => Self::UnsupportedSysvar,
ILLEGAL_OWNER => Self::IllegalOwner,
Expand Down Expand Up @@ -182,7 +182,7 @@ impl From<ProgramError> for u64 {
ProgramError::AccountBorrowFailed => ACCOUNT_BORROW_FAILED,
ProgramError::MaxSeedLengthExceeded => MAX_SEED_LENGTH_EXCEEDED,
ProgramError::InvalidSeeds => INVALID_SEEDS,
ProgramError::BorshIoError(_) => BORSH_IO_ERROR,
ProgramError::BorshIoError => BORSH_IO_ERROR,
ProgramError::AccountNotRentExempt => ACCOUNT_NOT_RENT_EXEMPT,
ProgramError::UnsupportedSysvar => UNSUPPORTED_SYSVAR,
ProgramError::IllegalOwner => ILLEGAL_OWNER,
Expand Down

0 comments on commit 1704c36

Please sign in to comment.