Return errors in Data peeling

Change-Id: I3e0ae581e83ebbcf0d343b758dff033ddc9b362e
This commit is contained in:
Reisen 2021-06-29 12:59:52 +00:00
parent e6317449d5
commit 21c7399d55
3 changed files with 17 additions and 15 deletions

View File

@ -57,6 +57,8 @@ enum Error {
VAAAlreadyExecuted, VAAAlreadyExecuted,
} }
/// Translate from program specific errors to Solitaire framework errors. Log the error on the way
/// out of the program for debugging.
impl From<Error> for SolitaireError { impl From<Error> for SolitaireError {
fn from(e: Error) -> SolitaireError { fn from(e: Error) -> SolitaireError {
msg!("ProgramError: {:?}", e); msg!("ProgramError: {:?}", e);

View File

@ -24,6 +24,9 @@ pub enum SolitaireError {
/// The AccountInfo has an invalid owner. /// The AccountInfo has an invalid owner.
InvalidOwner(Pubkey), InvalidOwner(Pubkey),
/// The AccountInfo is non-writeable where a writeable key was expected.
NonWriteableAccount(Pubkey),
/// The instruction payload itself could not be deserialized. /// The instruction payload itself could not be deserialized.
InstructionDeserializeFailed(std::io::Error), InstructionDeserializeFailed(std::io::Error),
@ -56,10 +59,9 @@ impl From<std::io::Error> for SolitaireError {
impl Into<ProgramError> for SolitaireError { impl Into<ProgramError> for SolitaireError {
fn into(self) -> ProgramError { fn into(self) -> ProgramError {
if let SolitaireError::ProgramError(e) = self { match self {
return e; SolitaireError::ProgramError(e) => return e,
_ => ProgramError::Custom(0),
} }
// TODO
ProgramError::Custom(0)
} }
} }

View File

@ -147,25 +147,22 @@ impl<
> Peel<'a, 'b, 'c> for Data<'b, T, IsInitialized> > Peel<'a, 'b, 'c> for Data<'b, T, IsInitialized>
{ {
fn peel<I>(ctx: &'c mut Context<'a, 'b, 'c, I>) -> Result<Self> { fn peel<I>(ctx: &'c mut Context<'a, 'b, 'c, I>) -> Result<Self> {
let mut initialized = false;
// If we're initializing the type, we should emit system/rent as deps. // If we're initializing the type, we should emit system/rent as deps.
let data: T = match IsInitialized { let (initialized, data): (bool, T) = match IsInitialized {
AccountState::Uninitialized => { AccountState::Uninitialized => {
if **ctx.info().lamports.borrow() != 0 { if **ctx.info().lamports.borrow() != 0 {
return Err(SolitaireError::AlreadyInitialized(*ctx.info().key)); return Err(SolitaireError::AlreadyInitialized(*ctx.info().key));
} }
T::default() (false, T::default())
} }
AccountState::Initialized => { AccountState::Initialized => {
initialized = true; (true, T::try_from_slice(&mut *ctx.info().data.borrow_mut())?)
T::try_from_slice(&mut *ctx.info().data.borrow_mut()).expect("Blew up in Initialized")
} }
AccountState::MaybeInitialized => { AccountState::MaybeInitialized => {
if **ctx.info().lamports.borrow() == 0 { if **ctx.info().lamports.borrow() == 0 {
T::default() (false, T::default())
} else { } else {
initialized = true; (true, T::try_from_slice(&mut *ctx.info().data.borrow_mut())?)
T::try_from_slice(&mut *ctx.info().data.borrow_mut())?
} }
} }
}; };
@ -198,13 +195,14 @@ impl<
} }
fn persist(&self, program_id: &Pubkey) -> Result<()> { fn persist(&self, program_id: &Pubkey) -> Result<()> {
// Only write to accounts owned by us // TODO: Introduce Mut<> to solve the check we really want to make here.
if self.0.owner != program_id { if self.0.owner != program_id {
return Ok(()); return Ok(());
} }
// It is also a malformed program to attempt to write to a non-writeable account.
if !self.0.is_writable { if !self.0.is_writable {
// TODO this needs to be checked properly return Err(SolitaireError::NonWriteableAccount(*self.0.key));
return Ok(());
} }
self.1.serialize(&mut *self.0.data.borrow_mut())?; self.1.serialize(&mut *self.0.data.borrow_mut())?;