Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lang: new internal writer to use bpf mem syscalls #1589

Merged
merged 5 commits into from
Mar 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ incremented for features.
### Features

* lang: Add new `AccountSysvarMismatch` error code and test cases for sysvars ([#1535](https://github.com/project-serum/anchor/pull/1535)).
* lang: Replace `std::io::Cursor` with a custom `Write` impl that uses the Solana mem syscalls ([#1589](https://github.com/project-serum/anchor/pull/1589)).
* spl: Add support for revoke instruction ([#1493](https://github.com/project-serum/anchor/pull/1493)).

### Fixes
Expand Down
5 changes: 3 additions & 2 deletions lang/src/accounts/account.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Account container that checks ownership on deserialization.

use crate::bpf_writer::BpfWriter;
use crate::error::ErrorCode;
use crate::*;
use solana_program::account_info::AccountInfo;
Expand Down Expand Up @@ -333,8 +334,8 @@ impl<'info, T: AccountSerialize + AccountDeserialize + Owner + Clone> AccountsEx
let info = self.to_account_info();
let mut data = info.try_borrow_mut_data()?;
let dst: &mut [u8] = &mut data;
let mut cursor = std::io::Cursor::new(dst);
self.account.try_serialize(&mut cursor)?;
let mut writer = BpfWriter::new(dst);
self.account.try_serialize(&mut writer)?;
}
Ok(())
}
Expand Down
5 changes: 3 additions & 2 deletions lang/src/accounts/account_loader.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Type facilitating on demand zero copy deserialization.

use crate::bpf_writer::BpfWriter;
use crate::error::ErrorCode;
use crate::{
Accounts, AccountsClose, AccountsExit, Owner, Result, ToAccountInfo, ToAccountInfos,
Expand Down Expand Up @@ -225,8 +226,8 @@ impl<'info, T: ZeroCopy + Owner> AccountsExit<'info> for AccountLoader<'info, T>
fn exit(&self, _program_id: &Pubkey) -> Result<()> {
let mut data = self.acc_info.try_borrow_mut_data()?;
let dst: &mut [u8] = &mut data;
let mut cursor = std::io::Cursor::new(dst);
cursor.write_all(&T::discriminator()).unwrap();
let mut writer = BpfWriter::new(dst);
writer.write_all(&T::discriminator()).unwrap();
Ok(())
}
}
Expand Down
5 changes: 3 additions & 2 deletions lang/src/accounts/loader.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::bpf_writer::BpfWriter;
use crate::error::ErrorCode;
use crate::{
Accounts, AccountsClose, AccountsExit, Result, ToAccountInfo, ToAccountInfos, ToAccountMetas,
Expand Down Expand Up @@ -168,8 +169,8 @@ impl<'info, T: ZeroCopy> AccountsExit<'info> for Loader<'info, T> {
fn exit(&self, _program_id: &Pubkey) -> Result<()> {
let mut data = self.acc_info.try_borrow_mut_data()?;
let dst: &mut [u8] = &mut data;
let mut cursor = std::io::Cursor::new(dst);
cursor.write_all(&T::discriminator()).unwrap();
let mut writer = BpfWriter::new(dst);
writer.write_all(&T::discriminator()).unwrap();
Ok(())
}
}
Expand Down
5 changes: 3 additions & 2 deletions lang/src/accounts/program_account.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[allow(deprecated)]
use crate::accounts::cpi_account::CpiAccount;
use crate::bpf_writer::BpfWriter;
use crate::error::ErrorCode;
use crate::{
AccountDeserialize, AccountSerialize, Accounts, AccountsClose, AccountsExit, Result,
Expand Down Expand Up @@ -98,8 +99,8 @@ impl<'info, T: AccountSerialize + AccountDeserialize + Clone> AccountsExit<'info
let info = self.to_account_info();
let mut data = info.try_borrow_mut_data()?;
let dst: &mut [u8] = &mut data;
let mut cursor = std::io::Cursor::new(dst);
self.inner.account.try_serialize(&mut cursor)?;
let mut writer = BpfWriter::new(dst);
self.inner.account.try_serialize(&mut writer)?;
Ok(())
}
}
Expand Down
5 changes: 3 additions & 2 deletions lang/src/accounts/state.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[allow(deprecated)]
use crate::accounts::cpi_account::CpiAccount;
use crate::bpf_writer::BpfWriter;
use crate::error::ErrorCode;
use crate::{
AccountDeserialize, AccountSerialize, Accounts, AccountsExit, Result, ToAccountInfo,
Expand Down Expand Up @@ -148,8 +149,8 @@ impl<'info, T: AccountSerialize + AccountDeserialize + Clone> AccountsExit<'info
let info = self.to_account_info();
let mut data = info.try_borrow_mut_data()?;
let dst: &mut [u8] = &mut data;
let mut cursor = std::io::Cursor::new(dst);
self.inner.account.try_serialize(&mut cursor)?;
let mut writer = BpfWriter::new(dst);
self.inner.account.try_serialize(&mut writer)?;
Ok(())
}
}
Expand Down
46 changes: 46 additions & 0 deletions lang/src/bpf_writer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use solana_program::program_memory::sol_memcpy;
use std::cmp;
use std::io::{self, Write};

#[derive(Debug, Default)]
pub struct BpfWriter<T> {
inner: T,
pos: u64,
}

impl<T> BpfWriter<T> {
pub fn new(inner: T) -> Self {
Self { inner, pos: 0 }
}
}

impl Write for BpfWriter<&mut [u8]> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if self.pos >= self.inner.len() as u64 {
return Ok(0);
}

let amt = cmp::min(
self.inner.len().saturating_sub(self.pos as usize),
buf.len(),
);
sol_memcpy(&mut self.inner[(self.pos as usize)..], buf, amt);
self.pos += amt as u64;
Ok(amt)
}

fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
if self.write(buf)? == buf.len() {
Ok(())
} else {
Err(io::Error::new(
io::ErrorKind::WriteZero,
"failed to write whole buffer",
))
}
}
callensm marked this conversation as resolved.
Show resolved Hide resolved

fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
5 changes: 3 additions & 2 deletions lang/src/common.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::bpf_writer::BpfWriter;
use crate::error::ErrorCode;
use crate::prelude::error;
use crate::Result;
Expand All @@ -14,8 +15,8 @@ pub fn close<'info>(info: AccountInfo<'info>, sol_destination: AccountInfo<'info
// Mark the account discriminator as closed.
let mut data = info.try_borrow_mut_data()?;
let dst: &mut [u8] = &mut data;
let mut cursor = std::io::Cursor::new(dst);
cursor
let mut writer = BpfWriter::new(dst);
writer
.write_all(&crate::__private::CLOSED_ACCOUNT_DISCRIMINATOR)
.map_err(|_| error!(ErrorCode::AccountDidNotSerialize))
}
1 change: 1 addition & 0 deletions lang/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use std::io::Write;
mod account_meta;
pub mod accounts;
mod bpf_upgradeable_state;
mod bpf_writer;
mod common;
pub mod context;
mod ctor;
Expand Down