Seperate RefCells lamports and data (#8021)

This commit is contained in:
Jack May 2020-01-29 21:15:04 -08:00 committed by GitHub
parent d5ff5f4739
commit b19f730527
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 33 additions and 52 deletions

View File

@ -16,32 +16,32 @@ fn process_instruction(
match instruction_data[0] { match instruction_data[0] {
1 => { 1 => {
info!("modify first account data"); info!("modify first account data");
accounts[2].borrow_mut().data[0] = 1; accounts[2].data.borrow_mut()[0] = 1;
} }
2 => { 2 => {
info!("modify first account data"); info!("modify first account data");
accounts[3].borrow_mut().data[0] = 2; accounts[3].data.borrow_mut()[0] = 2;
} }
3 => { 3 => {
info!("modify both account data"); info!("modify both account data");
accounts[2].borrow_mut().data[0] += 1; accounts[2].data.borrow_mut()[0] += 1;
accounts[3].borrow_mut().data[0] += 2; accounts[3].data.borrow_mut()[0] += 2;
} }
4 => { 4 => {
info!("modify first account lamports"); info!("modify first account lamports");
*accounts[1].borrow_mut().lamports -= 1; **accounts[1].lamports.borrow_mut() -= 1;
*accounts[2].borrow_mut().lamports += 1; **accounts[2].lamports.borrow_mut() += 1;
} }
5 => { 5 => {
info!("modify first account lamports"); info!("modify first account lamports");
*accounts[1].borrow_mut().lamports -= 2; **accounts[1].lamports.borrow_mut() -= 2;
*accounts[3].borrow_mut().lamports += 2; **accounts[3].lamports.borrow_mut() += 2;
} }
6 => { 6 => {
info!("modify both account lamports"); info!("modify both account lamports");
*accounts[1].borrow_mut().lamports -= 3; **accounts[1].lamports.borrow_mut() -= 3;
*accounts[2].borrow_mut().lamports += 1; **accounts[2].lamports.borrow_mut() += 1;
*accounts[3].borrow_mut().lamports += 2; **accounts[3].lamports.borrow_mut() += 2;
} }
_ => { _ => {
info!("Unrecognized command"); info!("Unrecognized command");

View File

@ -12,7 +12,7 @@ fn process_instruction(
// account 0 is the mint and not owned by this program, any debit of its lamports // 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 // should result in a failed program execution. Test to ensure that this debit
// is seen by the runtime and fails as expected // is seen by the runtime and fails as expected
*accounts[0].borrow_mut().lamports -= 1; **accounts[0].lamports.borrow_mut() -= 1;
SUCCESS SUCCESS
} }

View File

@ -1,17 +1,6 @@
use crate::{account::Account, pubkey::Pubkey}; use crate::{account::Account, pubkey::Pubkey};
use std::{ use std::{cell::RefCell, cmp, fmt, rc::Rc};
cell::{Ref, RefCell, RefMut},
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 /// Account information
#[derive(Clone)] #[derive(Clone)]
pub struct AccountInfo<'a> { pub struct AccountInfo<'a> {
@ -20,7 +9,9 @@ pub struct AccountInfo<'a> {
// Was the transaction signed by this account's public key? // Was the transaction signed by this account's public key?
pub is_signer: bool, pub is_signer: bool,
/// Account members that are mutable by the program /// Account members that are mutable by the program
pub m: Rc<RefCell<AccountInfoMut<'a>>>, pub lamports: Rc<RefCell<&'a mut u64>>,
/// Account members that are mutable by the program
pub data: Rc<RefCell<&'a mut [u8]>>,
/// Program that owns this account /// Program that owns this account
pub owner: &'a Pubkey, pub owner: &'a Pubkey,
} }
@ -31,7 +22,7 @@ impl<'a> fmt::Debug for AccountInfo<'a> {
let data_str = if data_len > 0 { let data_str = if data_len > 0 {
format!( format!(
" data: {}", " data: {}",
hex::encode(self.borrow().data[..data_len].to_vec()) hex::encode(self.data.borrow()[..data_len].to_vec())
) )
} else { } else {
"".to_string() "".to_string()
@ -61,23 +52,15 @@ impl<'a> AccountInfo<'a> {
} }
pub fn lamports(&self) -> u64 { pub fn lamports(&self) -> u64 {
*self.borrow().lamports **self.lamports.borrow()
} }
pub fn data_len(&self) -> usize { pub fn data_len(&self) -> usize {
self.borrow().data.len() self.data.borrow().len()
} }
pub fn data_is_empty(&self) -> bool { pub fn data_is_empty(&self) -> bool {
self.borrow().data.is_empty() self.data.borrow().is_empty()
}
pub fn borrow(&self) -> Ref<AccountInfoMut> {
self.m.borrow()
}
pub fn borrow_mut(&self) -> RefMut<AccountInfoMut<'a>> {
self.m.borrow_mut()
} }
pub fn new( pub fn new(
@ -90,20 +73,21 @@ impl<'a> AccountInfo<'a> {
Self { Self {
key, key,
is_signer, is_signer,
m: Rc::new(RefCell::new(AccountInfoMut { lamports, data })), lamports: Rc::new(RefCell::new(lamports)),
data: Rc::new(RefCell::new(data)),
owner, owner,
} }
} }
pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> { pub fn deserialize_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, bincode::Error> {
bincode::deserialize(&self.borrow().data) bincode::deserialize(&self.data.borrow())
} }
pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> { pub fn serialize_data<T: serde::Serialize>(&mut self, state: &T) -> Result<(), bincode::Error> {
if bincode::serialized_size(state)? > self.data_len() as u64 { if bincode::serialized_size(state)? > self.data_len() as u64 {
return Err(Box::new(bincode::ErrorKind::SizeLimit)); 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)
} }
} }

View File

@ -3,11 +3,7 @@
#![cfg(feature = "program")] #![cfg(feature = "program")]
extern crate alloc; extern crate alloc;
use crate::{account_info::AccountInfo, pubkey::Pubkey};
use crate::{
account_info::{AccountInfo, AccountInfoMut},
pubkey::Pubkey,
};
use alloc::vec::Vec; use alloc::vec::Vec;
use std::{ use std::{
cell::RefCell, cell::RefCell,
@ -79,25 +75,26 @@ pub unsafe fn deserialize<'a>(input: *mut u8) -> (&'a Pubkey, Vec<AccountInfo<'a
offset += size_of::<Pubkey>(); offset += size_of::<Pubkey>();
#[allow(clippy::cast_ptr_alignment)] #[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::<u64>(); offset += size_of::<u64>();
#[allow(clippy::cast_ptr_alignment)] #[allow(clippy::cast_ptr_alignment)]
let data_len = *(input.add(offset) as *const u64) as usize; let data_len = *(input.add(offset) as *const u64) as usize;
offset += size_of::<u64>(); offset += size_of::<u64>();
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; offset += data_len;
let owner: &Pubkey = &*(input.add(offset) as *const Pubkey); let owner: &Pubkey = &*(input.add(offset) as *const Pubkey);
offset += size_of::<Pubkey>(); offset += size_of::<Pubkey>();
let m = Rc::new(RefCell::new(AccountInfoMut { lamports, data }));
accounts.push(AccountInfo { accounts.push(AccountInfo {
is_signer, is_signer,
key, key,
m, lamports,
data,
owner, owner,
}); });
} else { } else {

View File

@ -71,10 +71,10 @@ pub trait Sysvar:
bincode::serialize_into(&mut account.data[..], self).ok() bincode::serialize_into(&mut account.data[..], self).ok()
} }
fn from_account_info(account_info: &AccountInfo) -> Option<Self> { fn from_account_info(account_info: &AccountInfo) -> Option<Self> {
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<()> { 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<Self, InstructionError> { fn from_keyed_account(keyed_account: &KeyedAccount) -> Result<Self, InstructionError> {
if !Self::check_id(keyed_account.unsigned_key()) { if !Self::check_id(keyed_account.unsigned_key()) {