Implement account persistence
Accounts with data will now be persisted at the end of the program execution Change-Id: I1dd29f521f5c659ced5758203acf532b645f3b44
This commit is contained in:
parent
c3829b9266
commit
b3b083b08a
|
@ -68,10 +68,10 @@ fn main() -> Result<(), ErrBox> {
|
||||||
payer: Signer(payer),
|
payer: Signer(payer),
|
||||||
};
|
};
|
||||||
|
|
||||||
let init_args = types::BridgeConfig {
|
let init_args = bridge::instruction::Instruction::Initialize(types::BridgeConfig {
|
||||||
guardian_set_expiration_time: DEFAULT_GUARDIAN_SET_EXPIRATION_TIME,
|
guardian_set_expiration_time: DEFAULT_GUARDIAN_SET_EXPIRATION_TIME,
|
||||||
fee: DEFAULT_MESSAGE_FEE,
|
fee: DEFAULT_MESSAGE_FEE,
|
||||||
};
|
});
|
||||||
|
|
||||||
let ix_data = init_args.try_to_vec()?;
|
let ix_data = init_args.try_to_vec()?;
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,10 @@ impl<'a, 'b: 'a, 'c, T: DeserializePayload> Peel<'a, 'b, 'c> for PayloadMessage<
|
||||||
fn deps() -> Vec<Pubkey> {
|
fn deps() -> Vec<Pubkey> {
|
||||||
Data::<'b, PostedMessage, { AccountState::Initialized }>::deps()
|
Data::<'b, PostedMessage, { AccountState::Initialized }>::deps()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn persist(&self, program_id: &Pubkey) -> Result<()> {
|
||||||
|
Data::persist(&self.0, program_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, T: DeserializePayload> Deref for PayloadMessage<'b, T> {
|
impl<'b, T: DeserializePayload> Deref for PayloadMessage<'b, T> {
|
||||||
|
|
|
@ -80,7 +80,8 @@ pub use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Library name and version to print in entrypoint. Must be evaluated in this crate in order to do the right thing
|
/// Library name and version to print in entrypoint. Must be evaluated in this crate in order to do the right thing
|
||||||
pub const PKG_NAME_VERSION: &'static str = concat!(env!("CARGO_PKG_NAME"), " ", env!("CARGO_PKG_VERSION"));
|
pub const PKG_NAME_VERSION: &'static str =
|
||||||
|
concat!(env!("CARGO_PKG_NAME"), " ", env!("CARGO_PKG_VERSION"));
|
||||||
|
|
||||||
pub struct ExecutionContext<'a, 'b: 'a> {
|
pub struct ExecutionContext<'a, 'b: 'a> {
|
||||||
/// A reference to the program_id of the current program.
|
/// A reference to the program_id of the current program.
|
||||||
|
|
|
@ -41,7 +41,7 @@ macro_rules! solitaire {
|
||||||
Instruction::$row(ix_data) => {
|
Instruction::$row(ix_data) => {
|
||||||
let (mut accounts): ($row) = FromAccounts::from(p, &mut a.iter(), &()).unwrap();
|
let (mut accounts): ($row) = FromAccounts::from(p, &mut a.iter(), &()).unwrap();
|
||||||
$fn(&ExecutionContext{program_id: p, accounts: a}, &mut accounts, ix_data)?;
|
$fn(&ExecutionContext{program_id: p, accounts: a}, &mut accounts, ix_data)?;
|
||||||
accounts.persist();
|
Persist::persist(&accounts, p)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
@ -128,6 +128,10 @@ macro_rules! data_wrapper {
|
||||||
fn deps() -> Vec<Pubkey> {
|
fn deps() -> Vec<Pubkey> {
|
||||||
Data::<'_, $embed, { $state }>::deps()
|
Data::<'_, $embed, { $state }>::deps()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn persist(&self, program_id: &Pubkey) -> solitaire::Result<()> {
|
||||||
|
Data::<'_, $embed, { $state }>::persist(self, program_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> solitaire::processors::seeded::Owned for $name<'b> {
|
impl<'b> solitaire::processors::seeded::Owned for $name<'b> {
|
||||||
|
|
|
@ -26,6 +26,7 @@ use crate::{
|
||||||
Result,
|
Result,
|
||||||
SolitaireError,
|
SolitaireError,
|
||||||
};
|
};
|
||||||
|
use borsh::BorshSerialize;
|
||||||
|
|
||||||
/// Generic Peel trait. This provides a way to describe what each "peeled"
|
/// Generic Peel trait. This provides a way to describe what each "peeled"
|
||||||
/// layer of our constraints should check.
|
/// layer of our constraints should check.
|
||||||
|
@ -35,6 +36,8 @@ pub trait Peel<'a, 'b: 'a, 'c> {
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
|
||||||
fn deps() -> Vec<Pubkey>;
|
fn deps() -> Vec<Pubkey>;
|
||||||
|
|
||||||
|
fn persist(&self, program_id: &Pubkey) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Peel a Derived Key
|
/// Peel a Derived Key
|
||||||
|
@ -49,9 +52,14 @@ impl<'a, 'b: 'a, 'c, T: Peel<'a, 'b, 'c>, const Seed: &'static str> Peel<'a, 'b,
|
||||||
_ => Err(SolitaireError::InvalidDerive(*ctx.info().key).into()),
|
_ => Err(SolitaireError::InvalidDerive(*ctx.info().key).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deps() -> Vec<Pubkey> {
|
fn deps() -> Vec<Pubkey> {
|
||||||
T::deps()
|
T::deps()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn persist(&self, program_id: &Pubkey) -> Result<()> {
|
||||||
|
T::persist(self, program_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Peel a Signer.
|
/// Peel a Signer.
|
||||||
|
@ -62,9 +70,14 @@ impl<'a, 'b: 'a, 'c, T: Peel<'a, 'b, 'c>> Peel<'a, 'b, 'c> for Signer<T> {
|
||||||
_ => Err(SolitaireError::InvalidSigner(*ctx.info().key).into()),
|
_ => Err(SolitaireError::InvalidSigner(*ctx.info().key).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deps() -> Vec<Pubkey> {
|
fn deps() -> Vec<Pubkey> {
|
||||||
T::deps()
|
T::deps()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn persist(&self, program_id: &Pubkey) -> Result<()> {
|
||||||
|
T::persist(self, program_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expicitly depend upon the System account.
|
/// Expicitly depend upon the System account.
|
||||||
|
@ -75,9 +88,14 @@ impl<'a, 'b: 'a, 'c, T: Peel<'a, 'b, 'c>> Peel<'a, 'b, 'c> for System<T> {
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deps() -> Vec<Pubkey> {
|
fn deps() -> Vec<Pubkey> {
|
||||||
T::deps()
|
T::deps()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn persist(&self, program_id: &Pubkey) -> Result<()> {
|
||||||
|
T::persist(self, program_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Peel a Sysvar
|
/// Peel a Sysvar
|
||||||
|
@ -94,9 +112,14 @@ where
|
||||||
_ => Err(SolitaireError::InvalidSysvar(*ctx.info().key).into()),
|
_ => Err(SolitaireError::InvalidSysvar(*ctx.info().key).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deps() -> Vec<Pubkey> {
|
fn deps() -> Vec<Pubkey> {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn persist(&self, _program_id: &Pubkey) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is our structural recursion base case, the trait system will stop generating new nested
|
/// This is our structural recursion base case, the trait system will stop generating new nested
|
||||||
|
@ -108,12 +131,20 @@ impl<'a, 'b: 'a, 'c> Peel<'a, 'b, 'c> for Info<'b> {
|
||||||
fn deps() -> Vec<Pubkey> {
|
fn deps() -> Vec<Pubkey> {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
fn persist(&self, _program_id: &Pubkey) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is our structural recursion base case, the trait system will stop generating new nested
|
/// This is our structural recursion base case, the trait system will stop generating new nested
|
||||||
/// calls here.
|
/// calls here.
|
||||||
impl<'a, 'b: 'a, 'c, T: BorshDeserialize + Owned + Default, const IsInitialized: AccountState>
|
impl<
|
||||||
Peel<'a, 'b, 'c> for Data<'b, T, IsInitialized>
|
'a,
|
||||||
|
'b: 'a,
|
||||||
|
'c,
|
||||||
|
T: BorshDeserialize + BorshSerialize + Owned + Default,
|
||||||
|
const IsInitialized: AccountState,
|
||||||
|
> 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;
|
let mut initialized = false;
|
||||||
|
@ -165,4 +196,19 @@ impl<'a, 'b: 'a, 'c, T: BorshDeserialize + Owned + Default, const IsInitialized:
|
||||||
|
|
||||||
vec![sysvar::rent::ID, system_program::ID]
|
vec![sysvar::rent::ID, system_program::ID]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn persist(&self, program_id: &Pubkey) -> Result<()> {
|
||||||
|
// Only write to accounts owned by us
|
||||||
|
if self.0.owner != program_id {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
if !self.0.is_writable {
|
||||||
|
// TODO this needs to be checked properly
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.1.serialize(&mut *self.0.data.borrow_mut())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use solana_program::pubkey::Pubkey;
|
||||||
|
|
||||||
pub trait Persist {
|
pub trait Persist {
|
||||||
fn persist(self);
|
fn persist(&self, program_id: &Pubkey) -> crate::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,15 +129,16 @@ pub fn derive_from_accounts(input: TokenStream) -> TokenStream {
|
||||||
fn deps() -> Vec<solana_program::pubkey::Pubkey> {
|
fn deps() -> Vec<solana_program::pubkey::Pubkey> {
|
||||||
#deps_method
|
#deps_method
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn persist(&self, program_id: &solana_program::pubkey::Pubkey) -> solitaire::Result<()> {
|
||||||
|
solitaire::Persist::persist(self, program_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Macro generated implementation of Persist by Solitaire.
|
/// Macro generated implementation of Persist by Solitaire.
|
||||||
impl #type_impl_g solitaire::Persist for #name #type_g {
|
impl #type_impl_g solitaire::Persist for #name #type_g {
|
||||||
fn persist(self) {
|
fn persist(&self, program_id: &solana_program::pubkey::Pubkey) -> solitaire::Result<()> {
|
||||||
use borsh::BorshSerialize;
|
#persist_method
|
||||||
//self.guardian_set.serialize(
|
|
||||||
// &mut *self.guardian_set.0.data.borrow_mut()
|
|
||||||
//);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -256,24 +257,14 @@ fn generate_persist(name: &syn::Ident, data: &Data) -> TokenStream2 {
|
||||||
let ty = &f.ty;
|
let ty = &f.ty;
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
let #name: #ty = Peel::peel(&mut solitaire::Context::new(
|
Peel::persist(&self.#name, program_id)?;
|
||||||
pid,
|
|
||||||
iter,
|
|
||||||
data,
|
|
||||||
))?;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let names = fields.named.iter().map(|f| {
|
|
||||||
let name = &f.ident;
|
|
||||||
quote!(#name)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Write out our iterator and return the filled structure.
|
// Write out our iterator and return the filled structure.
|
||||||
quote! {
|
quote! {
|
||||||
use solana_program::account_info::next_account_info;
|
|
||||||
#(#recurse;)*
|
#(#recurse;)*
|
||||||
Ok(#name { #(#names,)* })
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue