From b19f73052732e565c56d32c16db0af6e69578d02 Mon Sep 17 00:00:00 2001 From: Jack May Date: Wed, 29 Jan 2020 21:15:04 -0800 Subject: [PATCH] Seperate RefCells lamports and data (#8021) --- programs/bpf/rust/dup_accounts/src/lib.rs | 22 ++++++------ programs/bpf/rust/external_spend/src/lib.rs | 2 +- sdk/src/account_info.rs | 40 +++++++-------------- sdk/src/entrypoint.rs | 17 ++++----- sdk/src/sysvar/mod.rs | 4 +-- 5 files changed, 33 insertions(+), 52 deletions(-) diff --git a/programs/bpf/rust/dup_accounts/src/lib.rs b/programs/bpf/rust/dup_accounts/src/lib.rs index 635a6a3ad0..744a73afbd 100644 --- a/programs/bpf/rust/dup_accounts/src/lib.rs +++ b/programs/bpf/rust/dup_accounts/src/lib.rs @@ -16,32 +16,32 @@ fn process_instruction( match instruction_data[0] { 1 => { info!("modify first account data"); - accounts[2].borrow_mut().data[0] = 1; + accounts[2].data.borrow_mut()[0] = 1; } 2 => { info!("modify first account data"); - accounts[3].borrow_mut().data[0] = 2; + accounts[3].data.borrow_mut()[0] = 2; } 3 => { info!("modify both account data"); - accounts[2].borrow_mut().data[0] += 1; - accounts[3].borrow_mut().data[0] += 2; + accounts[2].data.borrow_mut()[0] += 1; + accounts[3].data.borrow_mut()[0] += 2; } 4 => { info!("modify first account lamports"); - *accounts[1].borrow_mut().lamports -= 1; - *accounts[2].borrow_mut().lamports += 1; + **accounts[1].lamports.borrow_mut() -= 1; + **accounts[2].lamports.borrow_mut() += 1; } 5 => { info!("modify first account lamports"); - *accounts[1].borrow_mut().lamports -= 2; - *accounts[3].borrow_mut().lamports += 2; + **accounts[1].lamports.borrow_mut() -= 2; + **accounts[3].lamports.borrow_mut() += 2; } 6 => { info!("modify both account lamports"); - *accounts[1].borrow_mut().lamports -= 3; - *accounts[2].borrow_mut().lamports += 1; - *accounts[3].borrow_mut().lamports += 2; + **accounts[1].lamports.borrow_mut() -= 3; + **accounts[2].lamports.borrow_mut() += 1; + **accounts[3].lamports.borrow_mut() += 2; } _ => { info!("Unrecognized command"); diff --git a/programs/bpf/rust/external_spend/src/lib.rs b/programs/bpf/rust/external_spend/src/lib.rs index 445a0354a0..73bbf5d491 100644 --- a/programs/bpf/rust/external_spend/src/lib.rs +++ b/programs/bpf/rust/external_spend/src/lib.rs @@ -12,7 +12,7 @@ fn process_instruction( // account 0 is the mint and not owned by this program, any debit of its lamports // should result in a failed program execution. Test to ensure that this debit // is seen by the runtime and fails as expected - *accounts[0].borrow_mut().lamports -= 1; + **accounts[0].lamports.borrow_mut() -= 1; SUCCESS } diff --git a/sdk/src/account_info.rs b/sdk/src/account_info.rs index ff4bfd9b16..7d046cc783 100644 --- a/sdk/src/account_info.rs +++ b/sdk/src/account_info.rs @@ -1,17 +1,6 @@ use crate::{account::Account, pubkey::Pubkey}; -use std::{ - cell::{Ref, RefCell, RefMut}, - cmp, fmt, - rc::Rc, -}; +use std::{cell::RefCell, cmp, fmt, rc::Rc}; -/// Account information that is mutable by a program -pub struct AccountInfoMut<'a> { - /// Number of lamports owned by this account - pub lamports: &'a mut u64, - /// On-chain data within this account - pub data: &'a mut [u8], -} /// Account information #[derive(Clone)] pub struct AccountInfo<'a> { @@ -20,7 +9,9 @@ pub struct AccountInfo<'a> { // Was the transaction signed by this account's public key? pub is_signer: bool, /// Account members that are mutable by the program - pub m: Rc>>, + pub lamports: Rc>, + /// Account members that are mutable by the program + pub data: Rc>, /// Program that owns this account pub owner: &'a Pubkey, } @@ -31,7 +22,7 @@ impl<'a> fmt::Debug for AccountInfo<'a> { let data_str = if data_len > 0 { format!( " data: {}", - hex::encode(self.borrow().data[..data_len].to_vec()) + hex::encode(self.data.borrow()[..data_len].to_vec()) ) } else { "".to_string() @@ -61,23 +52,15 @@ impl<'a> AccountInfo<'a> { } pub fn lamports(&self) -> u64 { - *self.borrow().lamports + **self.lamports.borrow() } pub fn data_len(&self) -> usize { - self.borrow().data.len() + self.data.borrow().len() } pub fn data_is_empty(&self) -> bool { - self.borrow().data.is_empty() - } - - pub fn borrow(&self) -> Ref { - self.m.borrow() - } - - pub fn borrow_mut(&self) -> RefMut> { - self.m.borrow_mut() + self.data.borrow().is_empty() } pub fn new( @@ -90,20 +73,21 @@ impl<'a> AccountInfo<'a> { Self { key, is_signer, - m: Rc::new(RefCell::new(AccountInfoMut { lamports, data })), + lamports: Rc::new(RefCell::new(lamports)), + data: Rc::new(RefCell::new(data)), owner, } } pub fn deserialize_data(&self) -> Result { - bincode::deserialize(&self.borrow().data) + bincode::deserialize(&self.data.borrow()) } pub fn serialize_data(&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.borrow_mut().data[..], state) + bincode::serialize_into(&mut self.data.borrow_mut()[..], state) } } diff --git a/sdk/src/entrypoint.rs b/sdk/src/entrypoint.rs index 925fe2cf1b..74e5614115 100644 --- a/sdk/src/entrypoint.rs +++ b/sdk/src/entrypoint.rs @@ -3,11 +3,7 @@ #![cfg(feature = "program")] extern crate alloc; - -use crate::{ - account_info::{AccountInfo, AccountInfoMut}, - pubkey::Pubkey, -}; +use crate::{account_info::AccountInfo, pubkey::Pubkey}; use alloc::vec::Vec; use std::{ cell::RefCell, @@ -79,25 +75,26 @@ pub unsafe fn deserialize<'a>(input: *mut u8) -> (&'a Pubkey, Vec(); #[allow(clippy::cast_ptr_alignment)] - let lamports = &mut *(input.add(offset) as *mut u64); + let lamports = Rc::new(RefCell::new(&mut *(input.add(offset) as *mut u64))); offset += size_of::(); #[allow(clippy::cast_ptr_alignment)] let data_len = *(input.add(offset) as *const u64) as usize; offset += size_of::(); - let data = { from_raw_parts_mut(input.add(offset), data_len) }; + let data = Rc::new(RefCell::new({ + from_raw_parts_mut(input.add(offset), data_len) + })); offset += data_len; let owner: &Pubkey = &*(input.add(offset) as *const Pubkey); offset += size_of::(); - let m = Rc::new(RefCell::new(AccountInfoMut { lamports, data })); - accounts.push(AccountInfo { is_signer, key, - m, + lamports, + data, owner, }); } else { diff --git a/sdk/src/sysvar/mod.rs b/sdk/src/sysvar/mod.rs index c0743b69cf..3bdd2e4150 100644 --- a/sdk/src/sysvar/mod.rs +++ b/sdk/src/sysvar/mod.rs @@ -71,10 +71,10 @@ pub trait Sysvar: bincode::serialize_into(&mut account.data[..], self).ok() } fn from_account_info(account_info: &AccountInfo) -> Option { - bincode::deserialize(&account_info.m.borrow().data).ok() + bincode::deserialize(&account_info.data.borrow()).ok() } fn to_account_info(&self, account_info: &mut AccountInfo) -> Option<()> { - bincode::serialize_into(&mut account_info.m.borrow_mut().data[..], self).ok() + bincode::serialize_into(&mut account_info.data.borrow_mut()[..], self).ok() } fn from_keyed_account(keyed_account: &KeyedAccount) -> Result { if !Self::check_id(keyed_account.unsigned_key()) {