Add peel mutability checks for accounts.
Change-Id: Ic6a6fadd13a2b41d60a0c98f3b5d80d23ac263a6
This commit is contained in:
parent
72951531f6
commit
76066c8cc6
|
@ -12,6 +12,9 @@ pub type ErrBox = Box<dyn std::error::Error>;
|
|||
/// There are several places in Solitaire that might fail, we want descriptive errors.
|
||||
#[derive(Debug)]
|
||||
pub enum SolitaireError {
|
||||
/// The AccountInfo parser expected a mutable key where a readonly was found, or vice versa.
|
||||
InvalidMutability(Pubkey),
|
||||
|
||||
/// The AccountInfo parser expected a Signer, but the account did not sign.
|
||||
InvalidSigner(Pubkey),
|
||||
|
||||
|
|
|
@ -62,6 +62,26 @@ impl<'a, 'b: 'a, 'c, T: Peel<'a, 'b, 'c>, const Seed: &'static str> Peel<'a, 'b,
|
|||
}
|
||||
}
|
||||
|
||||
/// Peel a Mutable key.
|
||||
impl<'a, 'b: 'a, 'c, T: Peel<'a, 'b, 'c>> Peel<'a, 'b, 'c> for Mut<T>
|
||||
{
|
||||
fn peel<I>(mut ctx: &'c mut Context<'a, 'b, 'c, I>) -> Result<Self> {
|
||||
ctx.immutable = false;
|
||||
match ctx.info().is_writable {
|
||||
true => T::peel(ctx).map(|v| Mut(v)),
|
||||
_ => Err(SolitaireError::InvalidMutability(*ctx.info().key).into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn deps() -> Vec<Pubkey> {
|
||||
T::deps()
|
||||
}
|
||||
|
||||
fn persist(&self, program_id: &Pubkey) -> Result<()> {
|
||||
T::persist(self, program_id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Peel a Signer.
|
||||
impl<'a, 'b: 'a, 'c, T: Peel<'a, 'b, 'c>> Peel<'a, 'b, 'c> for Signer<T> {
|
||||
fn peel<I>(ctx: &'c mut Context<'a, 'b, 'c, I>) -> Result<Self> {
|
||||
|
@ -126,6 +146,10 @@ where
|
|||
/// calls here.
|
||||
impl<'a, 'b: 'a, 'c> Peel<'a, 'b, 'c> for Info<'b> {
|
||||
fn peel<I>(ctx: &'c mut Context<'a, 'b, 'c, I>) -> Result<Self> {
|
||||
if ctx.immutable && ctx.info().is_writable {
|
||||
return Err(SolitaireError::InvalidMutability(*ctx.info().key).into());
|
||||
}
|
||||
|
||||
Ok(ctx.info().clone())
|
||||
}
|
||||
fn deps() -> Vec<Pubkey> {
|
||||
|
@ -147,6 +171,10 @@ impl<
|
|||
> Peel<'a, 'b, 'c> for Data<'b, T, IsInitialized>
|
||||
{
|
||||
fn peel<I>(ctx: &'c mut Context<'a, 'b, 'c, I>) -> Result<Self> {
|
||||
if ctx.immutable && ctx.info().is_writable {
|
||||
return Err(SolitaireError::InvalidMutability(*ctx.info().key).into());
|
||||
}
|
||||
|
||||
// If we're initializing the type, we should emit system/rent as deps.
|
||||
let (initialized, data): (bool, T) = match IsInitialized {
|
||||
AccountState::Uninitialized => {
|
||||
|
|
|
@ -14,22 +14,29 @@ pub struct Context<'a, 'b: 'a, 'c, T> {
|
|||
/// A reference to the program_id of the current program.
|
||||
pub this: &'a Pubkey,
|
||||
|
||||
/// A reference to the instructions account list, one or more keys may be extracted during
|
||||
/// the peeling process.
|
||||
pub iter: &'c mut Iter<'a, AccountInfo<'b>>,
|
||||
|
||||
/// This is a reference to the instruction data we are processing this
|
||||
/// account for.
|
||||
/// Reference to the data passed to the current instruction.
|
||||
pub data: &'a T,
|
||||
|
||||
/// An optional account info for this Peelable item, some fields may be other structures that
|
||||
/// do not themselves have an account info associated with the field.
|
||||
pub info: Option<&'a AccountInfo<'b>>,
|
||||
|
||||
/// Whether to enforce immutability.
|
||||
pub immutable: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a, 'c, T> Context<'a, 'b, 'c, T> {
|
||||
pub fn new(program: &'a Pubkey, iter: &'c mut Iter<'a, AccountInfo<'b>>, data: &'a T) -> Self {
|
||||
Context {
|
||||
this: program,
|
||||
info: None,
|
||||
immutable: true,
|
||||
iter,
|
||||
data,
|
||||
info: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,9 @@ use borsh::{
|
|||
BorshSerialize,
|
||||
};
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Mut<Next>(pub Next);
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Signer<Next>(pub Next);
|
||||
|
||||
|
@ -48,6 +51,19 @@ impl<T> DerefMut for Signer<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Mut<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { std::mem::transmute(&self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for Mut<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe { std::mem::transmute(&mut self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for System<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
|
Loading…
Reference in New Issue