Sysvar support (#16)

This commit is contained in:
Armani Ferrante 2021-01-11 09:22:25 -08:00 committed by GitHub
parent cddc4f6bb6
commit 17d62cbf30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 139 additions and 7 deletions

View File

@ -40,6 +40,7 @@ jobs:
- <<: *examples - <<: *examples
name: Runs the examples name: Runs the examples
script: script:
- pushd examples/sysvars && anchor test && popd
- pushd examples/tutorial/basic-0 && anchor test && popd - pushd examples/tutorial/basic-0 && anchor test && popd
- pushd examples/tutorial/basic-1 && anchor test && popd - pushd examples/tutorial/basic-1 && anchor test && popd
- pushd examples/tutorial/basic-2 && anchor test && popd - pushd examples/tutorial/basic-2 && anchor test && popd

View File

@ -4,7 +4,7 @@ use heck::SnakeCase;
pub fn virtual_manifest() -> String { pub fn virtual_manifest() -> String {
r#"[workspace] r#"[workspace]
members = [ members = [
"programs/*" "programs/*"
] ]
"# "#
.to_string() .to_string()
@ -47,10 +47,10 @@ use anchor::prelude::*;
#[program] #[program]
mod {} {{ mod {} {{
use super::*; use super::*;
pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {{ pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {{
Ok(()) Ok(())
}} }}
}} }}
#[derive(Accounts)] #[derive(Accounts)]

View File

@ -0,0 +1,2 @@
cluster = "localnet"
wallet = "~/.config/solana/id.json"

View File

@ -0,0 +1,4 @@
[workspace]
members = [
"programs/*"
]

View File

@ -0,0 +1,15 @@
[package]
name = "sysvars"
version = "0.1.0"
description = "Created with Anchor"
edition = "2018"
[lib]
crate-type = ["cdylib"]
name = "sysvars"
[dependencies]
borsh = { git = "https://github.com/project-serum/borsh", branch = "serum", features = ["serum-program"] }
solana-program = "1.4.3"
solana-sdk = { version = "1.3.14", default-features = false, features = ["program"] }
anchor = { git = "https://github.com/project-serum/anchor", features = ["derive"] }

View File

@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []

View File

@ -0,0 +1,18 @@
#![feature(proc_macro_hygiene)]
use anchor::prelude::*;
#[program]
mod sysvars {
use super::*;
pub fn sysvars(_ctx: Context<Sysvars>) -> ProgramResult {
Ok(())
}
}
#[derive(Accounts)]
pub struct Sysvars {
pub clock: Clock,
pub rent: Rent,
pub stake_history: StakeHistory,
}

View File

@ -0,0 +1,19 @@
const anchor = require('@project-serum/anchor');
describe('sysvars', () => {
// Configure the client to use the local cluster.
anchor.setProvider(anchor.Provider.local());
it('Is initialized!', async () => {
const program = anchor.workspace.Sysvars;
const tx = await program.rpc.sysvars({
accounts: {
clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
stakeHistory: anchor.web3.SYSVAR_STAKE_HISTORY_PUBKEY,
},
});
console.log("Your transaction signature", tx);
});
});

View File

@ -127,4 +127,15 @@ pub mod prelude {
pub use solana_sdk::entrypoint::ProgramResult; pub use solana_sdk::entrypoint::ProgramResult;
pub use solana_sdk::program_error::ProgramError; pub use solana_sdk::program_error::ProgramError;
pub use solana_sdk::pubkey::Pubkey; pub use solana_sdk::pubkey::Pubkey;
pub use solana_sdk::sysvar::clock::Clock;
pub use solana_sdk::sysvar::epoch_schedule::EpochSchedule;
pub use solana_sdk::sysvar::fees::Fees;
pub use solana_sdk::sysvar::instructions::Instructions;
pub use solana_sdk::sysvar::recent_blockhashes::RecentBlockhashes;
pub use solana_sdk::sysvar::rent::Rent;
pub use solana_sdk::sysvar::rewards::Rewards;
pub use solana_sdk::sysvar::slot_hashes::SlotHashes;
pub use solana_sdk::sysvar::slot_history::SlotHistory;
pub use solana_sdk::sysvar::stake_history::StakeHistory;
pub use solana_sdk::sysvar::Sysvar;
} }

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
AccountsStruct, Constraint, ConstraintBelongsTo, ConstraintLiteral, ConstraintOwner, AccountsStruct, Constraint, ConstraintBelongsTo, ConstraintLiteral, ConstraintOwner,
ConstraintSigner, Field, Ty, ConstraintSigner, Field, SysvarTy, Ty,
}; };
use quote::quote; use quote::quote;
@ -45,6 +45,7 @@ pub fn generate(accs: AccountsStruct) -> proc_macro2::TokenStream {
let info = match f.ty { let info = match f.ty {
Ty::AccountInfo => quote! { #ident }, Ty::AccountInfo => quote! { #ident },
Ty::ProgramAccount(_) => quote! { #ident.info }, Ty::ProgramAccount(_) => quote! { #ident.info },
_ => return quote! {},
}; };
match f.is_mut { match f.is_mut {
false => quote! {}, false => quote! {},
@ -108,6 +109,38 @@ pub fn generate_field(f: &Field) -> proc_macro2::TokenStream {
}, },
} }
} }
Ty::Sysvar(sysvar) => match sysvar {
SysvarTy::Clock => quote! {
let #ident = Clock::from_account_info(#ident)?;
},
SysvarTy::Rent => quote! {
let #ident = Rent::from_account_info(#ident)?;
},
SysvarTy::EpochSchedule => quote! {
let #ident = EpochSchedule::from_account_info(#ident)?;
},
SysvarTy::Fees => quote! {
let #ident = Fees::from_account_info(#ident)?;
},
SysvarTy::RecentBlockHashes => quote! {
let #ident = RecentBlockhashes::from_account_info(#ident)?;
},
SysvarTy::SlotHashes => quote! {
let #ident = SlotHashes::from_account_info(#ident)?;
},
SysvarTy::SlotHistory => quote! {
let #ident = SlotHistory::from_account_info(#ident)?;
},
SysvarTy::StakeHistory => quote! {
let #ident = StakeHistory::from_account_info(#ident)?;
},
SysvarTy::Instructions => quote! {
let #ident = Instructions::from_account_info(#ident)?;
},
SysvarTy::Rewards => quote! {
let #ident = Rewards::from_account_info(#ident)?;
},
},
}; };
let checks: Vec<proc_macro2::TokenStream> = f let checks: Vec<proc_macro2::TokenStream> = f
.constraints .constraints
@ -150,6 +183,7 @@ pub fn generate_constraint_signer(f: &Field, _c: &ConstraintSigner) -> proc_macr
let info = match f.ty { let info = match f.ty {
Ty::AccountInfo => quote! { #ident }, Ty::AccountInfo => quote! { #ident },
Ty::ProgramAccount(_) => quote! { #ident.info }, Ty::ProgramAccount(_) => quote! { #ident.info },
_ => panic!("Invalid syntax: signer cannot be specified."),
}; };
quote! { quote! {
if !#info.is_signer { if !#info.is_signer {
@ -172,6 +206,7 @@ pub fn generate_constraint_owner(f: &Field, c: &ConstraintOwner) -> proc_macro2:
let info = match f.ty { let info = match f.ty {
Ty::AccountInfo => quote! { #ident }, Ty::AccountInfo => quote! { #ident },
Ty::ProgramAccount(_) => quote! { #ident.info }, Ty::ProgramAccount(_) => quote! { #ident.info },
_ => panic!("Invalid syntax: owner cannot be specified."),
}; };
match c { match c {
ConstraintOwner::Skip => quote! {}, ConstraintOwner::Skip => quote! {},

View File

@ -72,6 +72,21 @@ pub struct Field {
pub enum Ty { pub enum Ty {
AccountInfo, AccountInfo,
ProgramAccount(ProgramAccountTy), ProgramAccount(ProgramAccountTy),
Sysvar(SysvarTy),
}
#[derive(PartialEq)]
pub enum SysvarTy {
Clock,
Rent,
EpochSchedule,
Fees,
RecentBlockHashes,
SlotHashes,
SlotHistory,
StakeHistory,
Instructions,
Rewards,
} }
#[derive(PartialEq)] #[derive(PartialEq)]

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
AccountsStruct, Constraint, ConstraintBelongsTo, ConstraintLiteral, ConstraintOwner, AccountsStruct, Constraint, ConstraintBelongsTo, ConstraintLiteral, ConstraintOwner,
ConstraintSigner, Field, ProgramAccountTy, Ty, ConstraintSigner, Field, ProgramAccountTy, SysvarTy, Ty,
}; };
pub fn parse(strct: &syn::ItemStruct) -> AccountsStruct { pub fn parse(strct: &syn::ItemStruct) -> AccountsStruct {
@ -69,6 +69,16 @@ fn parse_ty(f: &syn::Field) -> Ty {
match segments.ident.to_string().as_str() { match segments.ident.to_string().as_str() {
"ProgramAccount" => Ty::ProgramAccount(parse_program_account(&path)), "ProgramAccount" => Ty::ProgramAccount(parse_program_account(&path)),
"AccountInfo" => Ty::AccountInfo, "AccountInfo" => Ty::AccountInfo,
"Clock" => Ty::Sysvar(SysvarTy::Clock),
"Rent" => Ty::Sysvar(SysvarTy::Rent),
"EpochSchedule" => Ty::Sysvar(SysvarTy::EpochSchedule),
"Fees" => Ty::Sysvar(SysvarTy::Fees),
"RecentBlockhashes" => Ty::Sysvar(SysvarTy::RecentBlockHashes),
"SlotHashes" => Ty::Sysvar(SysvarTy::SlotHashes),
"SlotHistory" => Ty::Sysvar(SysvarTy::SlotHistory),
"StakeHistory" => Ty::Sysvar(SysvarTy::StakeHistory),
"Instructions" => Ty::Sysvar(SysvarTy::Instructions),
"Rewards" => Ty::Sysvar(SysvarTy::Rewards),
_ => panic!("invalid type"), _ => panic!("invalid type"),
} }
} }