Implement Seeded trait and account creation
Change-Id: I355b88e07b872f8b4869fa9b7fa8dcae4806527d
This commit is contained in:
parent
e2195c9b17
commit
88a94a9129
|
@ -2,6 +2,9 @@
|
|||
#![feature(const_generics_defaults)]
|
||||
#![allow(warnings)]
|
||||
|
||||
pub mod seeded;
|
||||
|
||||
pub use seeded::*;
|
||||
pub use rocksalt::*;
|
||||
|
||||
// Lacking:
|
||||
|
@ -32,6 +35,7 @@ pub use borsh::{BorshDeserialize, BorshSerialize};
|
|||
use solana_program::{
|
||||
account_info::next_account_info,
|
||||
instruction::AccountMeta,
|
||||
program::invoke_signed,
|
||||
program_error::ProgramError,
|
||||
program_pack::Pack,
|
||||
rent::Rent,
|
||||
|
@ -297,9 +301,57 @@ impl<T, const Seed: &'static str> DerefMut for Derive<T, Seed> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, const Seed: &'static str> Seeded for Derive<T, Seed> {
|
||||
fn seeds(self) -> Vec<Vec<Vec<u8>>> {
|
||||
vec![vec![Seed.try_to_vec().unwrap()]]
|
||||
pub trait Keyed {
|
||||
fn pubkey(&self) -> &Pubkey;
|
||||
}
|
||||
|
||||
impl<'r, T, const IsInitialized: bool, const Lazy: bool> Keyed
|
||||
for Data<'r, T, IsInitialized, Lazy>
|
||||
{
|
||||
fn pubkey(&self) -> &Pubkey {
|
||||
self.0.key
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Keyed for Signer<T>
|
||||
where
|
||||
T: Keyed,
|
||||
{
|
||||
fn pubkey(&self) -> &Pubkey {
|
||||
self.0.pubkey()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Var> Keyed for Sysvar<T, Var>
|
||||
where
|
||||
T: Keyed,
|
||||
{
|
||||
fn pubkey(&self) -> &Pubkey {
|
||||
self.0.pubkey()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Keyed for System<T>
|
||||
where
|
||||
T: Keyed,
|
||||
{
|
||||
fn pubkey(&self) -> &Pubkey {
|
||||
self.0.pubkey()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const Seed: &'static str> Keyed for Derive<T, Seed>
|
||||
where
|
||||
T: Keyed,
|
||||
{
|
||||
fn pubkey(&self) -> &Pubkey {
|
||||
self.0.pubkey()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Keyed for Info<'r> {
|
||||
fn pubkey(&self) -> &Pubkey {
|
||||
self.key
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,7 +387,7 @@ impl<const Seed: &'static str> Derive<AccountInfo<'_>, Seed> {
|
|||
space as u64,
|
||||
owner,
|
||||
);
|
||||
invoke_signed(&ix, ctx.accounts, &[&[Seed.as_bytes()]])
|
||||
Ok(invoke_signed(&ix, ctx.accounts, &[&[Seed.as_bytes()]])?)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,7 +407,7 @@ impl<const Seed: &'static str, T: BorshSerialize> Derive<Data<'_, T, Uninitializ
|
|||
size as u64,
|
||||
ctx.program_id,
|
||||
);
|
||||
invoke_signed(&ix, ctx.accounts, &[&[Seed.as_bytes()]])
|
||||
Ok(invoke_signed(&ix, ctx.accounts, &[&[Seed.as_bytes()]])?)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,6 +507,7 @@ impl<T> Wrap for Signer<T> {
|
|||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const Seed: &'static str> Wrap for Derive<T, Seed> {
|
||||
fn wrap(&self) -> Vec<AccountMeta> {
|
||||
todo!()
|
||||
|
@ -470,7 +523,7 @@ impl<'a, T: BorshSerialize, const IsInitialized: bool, const Lazy: bool> Wrap
|
|||
}
|
||||
|
||||
pub trait InstructionContext<'a> {
|
||||
fn verify(&self) -> Result<()> {
|
||||
fn verify(&self, program_id: &Pubkey) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
use crate::{
|
||||
system_instruction,
|
||||
AccountInfo,
|
||||
CreationLamports,
|
||||
Data,
|
||||
Deref,
|
||||
Derive,
|
||||
ExecutionContext,
|
||||
FromAccounts,
|
||||
Info,
|
||||
Keyed,
|
||||
Peel,
|
||||
Result,
|
||||
Signer,
|
||||
SolitaireError,
|
||||
System,
|
||||
Sysvar,
|
||||
Uninitialized,
|
||||
};
|
||||
use borsh::{BorshSchema, BorshSerialize};
|
||||
use solana_program::{program::invoke_signed, pubkey::Pubkey};
|
||||
|
||||
pub trait AccountSize {
|
||||
fn size(&self) -> usize;
|
||||
}
|
||||
|
||||
pub trait Seeded<I> {
|
||||
fn seeds(&self, accs: I) -> Vec<Vec<Vec<u8>>>;
|
||||
fn verify_derivation(&self, program_id: &Pubkey, accs: I) -> Result<()>
|
||||
where
|
||||
Self: Keyed,
|
||||
{
|
||||
let seeds = self.seeds(accs);
|
||||
let (derived, bump) = Pubkey::find_program_address(&[], program_id); //TODO
|
||||
if &derived == self.pubkey() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(SolitaireError::InvalidDerive(*self.pubkey()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Creatable<I> {
|
||||
fn create(
|
||||
&self,
|
||||
accs: I,
|
||||
ctx: &ExecutionContext,
|
||||
payer: &Pubkey,
|
||||
lamports: CreationLamports,
|
||||
) -> Result<()>;
|
||||
}
|
||||
|
||||
impl<T: BorshSerialize, const IsInitialized: bool> AccountSize for Data<'_, T, IsInitialized> {
|
||||
fn size(&self) -> usize {
|
||||
self.1.try_to_vec().unwrap().len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a, K, T: AccountSize + Seeded<K> + Keyed> Creatable<K> for T {
|
||||
fn create(
|
||||
&self,
|
||||
accs: K,
|
||||
ctx: &ExecutionContext<'_, '_>,
|
||||
payer: &Pubkey,
|
||||
lamports: CreationLamports,
|
||||
) -> Result<()> {
|
||||
let seeds = self.seeds(accs);
|
||||
let size = self.size();
|
||||
|
||||
let ix = system_instruction::create_account(
|
||||
payer,
|
||||
self.pubkey(),
|
||||
lamports.amount(size),
|
||||
size as u64,
|
||||
ctx.program_id,
|
||||
);
|
||||
Ok(invoke_signed(&ix, ctx.accounts, &[])?) // TODO use seeds
|
||||
}
|
||||
}
|
||||
|
||||
impl<const Seed: &'static str, T: BorshSerialize> Creatable<Option<()>>
|
||||
for Derive<Data<'_, T, Uninitialized>, Seed>
|
||||
{
|
||||
fn create(
|
||||
&self,
|
||||
_: Option<()>,
|
||||
ctx: &ExecutionContext,
|
||||
payer: &Pubkey,
|
||||
lamports: CreationLamports,
|
||||
) -> Result<()> {
|
||||
// Get serialized struct size
|
||||
let size = self.0.try_to_vec().unwrap().len();
|
||||
let ix = system_instruction::create_account(
|
||||
payer,
|
||||
self.0 .0.key,
|
||||
lamports.amount(size),
|
||||
size as u64,
|
||||
ctx.program_id,
|
||||
);
|
||||
Ok(invoke_signed(&ix, ctx.accounts, &[&[Seed.as_bytes()]])?)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue