Add sysvar support (#5838)
This commit is contained in:
parent
ee0c570d54
commit
a317e9513f
|
@ -70,6 +70,7 @@ fn main() {
|
|||
let rust_programs = [
|
||||
"128bit",
|
||||
"alloc",
|
||||
"clock",
|
||||
"dep_crate",
|
||||
"iter",
|
||||
"many_args",
|
||||
|
@ -77,7 +78,6 @@ fn main() {
|
|||
"noop",
|
||||
"panic",
|
||||
"param_passing",
|
||||
"tick_height",
|
||||
];
|
||||
for program in rust_programs.iter() {
|
||||
println!(
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
# Note: This crate must be built using build.sh
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-tick-height"
|
||||
name = "solana-bpf-rust-clock"
|
||||
version = "0.19.0-pre0"
|
||||
description = "Solana BPF noop program written in Rust"
|
||||
description = "Solana BPF clock sysvar test"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
|
@ -12,7 +12,6 @@ homepage = "https://solana.com/"
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
byteorder = { version = "1", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "0.19.0-pre0", default-features = false }
|
||||
|
||||
[features]
|
||||
|
@ -24,4 +23,4 @@ members = []
|
|||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
name = "solana_bpf_rust_tick_height"
|
||||
name = "solana_bpf_rust_clock"
|
|
@ -0,0 +1,28 @@
|
|||
//! @brief Example Rust-based BPF program that prints out the parameters passed to it
|
||||
|
||||
extern crate solana_sdk;
|
||||
use solana_sdk::{
|
||||
account_info::AccountInfo, entrypoint, entrypoint::SUCCESS, info, pubkey::Pubkey,
|
||||
sysvar::clock::Clock,
|
||||
};
|
||||
|
||||
entrypoint!(process_instruction);
|
||||
fn process_instruction(_program_id: &Pubkey, accounts: &mut [AccountInfo], _data: &[u8]) -> u32 {
|
||||
match Clock::from(&accounts[2]) {
|
||||
Some(clock) => {
|
||||
info!("slot, segment, epoch, stakers_epoch");
|
||||
info!(
|
||||
clock.slot,
|
||||
clock.segment, clock.epoch, clock.stakers_epoch, 0
|
||||
);
|
||||
assert_eq!(clock.slot, 42);
|
||||
}
|
||||
None => {
|
||||
info!("Failed to get clock from account 2");
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
info!("Success");
|
||||
SUCCESS
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
//! @brief Example Rust-based BPF program that prints out the parameters passed to it
|
||||
|
||||
extern crate solana_sdk;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use solana_sdk::{
|
||||
account_info::AccountInfo, entrypoint, entrypoint::SUCCESS, info, pubkey::Pubkey,
|
||||
};
|
||||
|
||||
entrypoint!(process_instruction);
|
||||
fn process_instruction(_program_id: &Pubkey, accounts: &mut [AccountInfo], _data: &[u8]) -> u32 {
|
||||
let tick_height = LittleEndian::read_u64(accounts[2].data);
|
||||
assert_eq!(10u64, tick_height);
|
||||
|
||||
info!("Success");
|
||||
SUCCESS
|
||||
}
|
|
@ -79,10 +79,12 @@ mod bpf {
|
|||
use super::*;
|
||||
use solana_sdk::bpf_loader;
|
||||
use solana_sdk::client::SyncClient;
|
||||
use solana_sdk::hash;
|
||||
use solana_sdk::instruction::{AccountMeta, Instruction};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::sysvar::clock;
|
||||
use std::io::Read;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[test]
|
||||
fn test_program_bpf_rust() {
|
||||
|
@ -91,10 +93,11 @@ mod bpf {
|
|||
let programs = [
|
||||
("solana_bpf_rust_128bit", true),
|
||||
("solana_bpf_rust_alloc", true),
|
||||
("solana_bpf_rust_clock", true),
|
||||
("solana_bpf_rust_dep_crate", true),
|
||||
("solana_bpf_rust_external_spend", false),
|
||||
("solana_bpf_rust_iter", true),
|
||||
("solana_bpf_rust_many_args", true),
|
||||
("solana_bpf_rust_external_spend", false),
|
||||
("solana_bpf_rust_noop", true),
|
||||
("solana_bpf_rust_panic", false),
|
||||
("solana_bpf_rust_param_passing", true),
|
||||
|
@ -111,12 +114,9 @@ mod bpf {
|
|||
mint_keypair,
|
||||
..
|
||||
} = create_genesis_block(50);
|
||||
let bank = Bank::new(&genesis_block);
|
||||
|
||||
// register some ticks, used by solana_bpf_rust_tick_height
|
||||
for i in 0..10 {
|
||||
bank.register_tick(&hash::hash(format!("hashing {}", i).as_bytes()));
|
||||
}
|
||||
let bank = Arc::new(Bank::new(&genesis_block));
|
||||
// Create bank with specific slot, used by solana_bpf_rust_clock test
|
||||
let bank = Bank::new_from_parent(&bank, &Pubkey::default(), 42);
|
||||
let bank_client = BankClient::new(bank);
|
||||
|
||||
// Call user program
|
||||
|
@ -124,6 +124,7 @@ mod bpf {
|
|||
let account_metas = vec![
|
||||
AccountMeta::new(mint_keypair.pubkey(), true),
|
||||
AccountMeta::new(Keypair::new().pubkey(), false),
|
||||
AccountMeta::new(clock::id(), false),
|
||||
];
|
||||
let instruction = Instruction::new(program_id, &1u8, account_metas);
|
||||
let result = bank_client.send_instruction(&mint_keypair, instruction);
|
||||
|
|
|
@ -179,7 +179,7 @@ pub fn process_instruction(
|
|||
me.delegate_stake(
|
||||
vote,
|
||||
stake,
|
||||
&sysvar::clock::from_keyed_account(&rest[1])?,
|
||||
&sysvar::clock_account::from_keyed_account(&rest[1])?,
|
||||
&config::from_keyed_account(&rest[2])?,
|
||||
)
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ pub fn process_instruction(
|
|||
me.withdraw(
|
||||
lamports,
|
||||
&mut to,
|
||||
&sysvar::clock::from_keyed_account(&sysvar[0])?,
|
||||
&sysvar::clock_account::from_keyed_account(&sysvar[0])?,
|
||||
&sysvar::stake_history::from_keyed_account(&sysvar[1])?,
|
||||
)
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ pub fn process_instruction(
|
|||
let vote = &mut vote[0];
|
||||
let clock = &rest[0];
|
||||
|
||||
me.deactivate_stake(vote, &sysvar::clock::from_keyed_account(&clock)?)
|
||||
me.deactivate_stake(vote, &sysvar::clock_account::from_keyed_account(&clock)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ mod tests {
|
|||
.iter()
|
||||
.map(|meta| {
|
||||
if sysvar::clock::check_id(&meta.pubkey) {
|
||||
sysvar::clock::create_account(1, 0, 0, 0, 0)
|
||||
sysvar::clock_account::new(1, 0, 0, 0, 0)
|
||||
} else if sysvar::rewards::check_id(&meta.pubkey) {
|
||||
sysvar::rewards::create_account(1, 0.0, 0.0)
|
||||
} else if sysvar::stake_history::check_id(&meta.pubkey) {
|
||||
|
@ -336,7 +336,7 @@ mod tests {
|
|||
KeyedAccount::new(
|
||||
&sysvar::clock::id(),
|
||||
false,
|
||||
&mut sysvar::clock::create_account(1, 0, 0, 0, 0)
|
||||
&mut sysvar::clock_account::new(1, 0, 0, 0, 0)
|
||||
),
|
||||
KeyedAccount::new(
|
||||
&config::id(),
|
||||
|
|
|
@ -42,7 +42,7 @@ pub fn process_instruction(
|
|||
// This instruction must be signed by `me`
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
let clock = sysvar::clock::from_keyed_account(&rest[0])?;
|
||||
let clock = sysvar::clock_account::from_keyed_account(&rest[0])?;
|
||||
storage_account.submit_mining_proof(
|
||||
sha_state,
|
||||
segment_index,
|
||||
|
@ -56,7 +56,7 @@ pub fn process_instruction(
|
|||
// This instruction must be signed by `me`
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
let clock = sysvar::clock::from_keyed_account(&rest[0])?;
|
||||
let clock = sysvar::clock_account::from_keyed_account(&rest[0])?;
|
||||
storage_account.advertise_storage_recent_blockhash(hash, segment, clock)
|
||||
}
|
||||
StorageInstruction::ClaimStorageReward => {
|
||||
|
@ -68,7 +68,7 @@ pub fn process_instruction(
|
|||
let (rewards_pools, owner) = rest.split_at_mut(1);
|
||||
|
||||
let rewards = sysvar::rewards::from_keyed_account(&rewards[0])?;
|
||||
let clock = sysvar::clock::from_keyed_account(&clock[0])?;
|
||||
let clock = sysvar::clock_account::from_keyed_account(&clock[0])?;
|
||||
let mut owner = StorageAccount::new(*owner[0].unsigned_key(), &mut owner[0].account);
|
||||
|
||||
storage_account.claim_storage_reward(&mut rewards_pools[0], clock, rewards, &mut owner)
|
||||
|
@ -84,7 +84,7 @@ pub fn process_instruction(
|
|||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
let me_id = storage_account.id;
|
||||
let clock = sysvar::clock::from_keyed_account(&clock[0])?;
|
||||
let clock = sysvar::clock_account::from_keyed_account(&clock[0])?;
|
||||
let mut rest: Vec<_> = rest
|
||||
.iter_mut()
|
||||
.map(|keyed_account| {
|
||||
|
|
|
@ -14,9 +14,9 @@ use solana_sdk::message::Message;
|
|||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||
use solana_sdk::system_instruction;
|
||||
use solana_sdk::sysvar::clock::Clock;
|
||||
use solana_sdk::sysvar::clock::{self, Clock};
|
||||
use solana_sdk::sysvar::rewards::Rewards;
|
||||
use solana_sdk::sysvar::{clock, rewards};
|
||||
use solana_sdk::sysvar::{clock_account, rewards};
|
||||
use solana_storage_api::id;
|
||||
use solana_storage_api::storage_contract::StorageAccount;
|
||||
use solana_storage_api::storage_contract::{ProofStatus, StorageContract, STORAGE_ACCOUNT_SPACE};
|
||||
|
@ -124,7 +124,7 @@ fn test_proof_bounds() {
|
|||
Hash::default(),
|
||||
);
|
||||
// the proof is for segment 0, need to move the slot into segment 2
|
||||
let mut clock_account = clock::create_account(1, 0, 0, 0, 0);
|
||||
let mut clock_account = clock_account::new(1, 0, 0, 0, 0);
|
||||
Clock::to(
|
||||
&Clock {
|
||||
slot: DEFAULT_SLOTS_PER_SEGMENT * 2,
|
||||
|
@ -152,7 +152,7 @@ fn test_serialize_overflow() {
|
|||
let clock_id = clock::id();
|
||||
let mut keyed_accounts = Vec::new();
|
||||
let mut user_account = Account::default();
|
||||
let mut clock_account = clock::create_account(1, 0, 0, 0, 0);
|
||||
let mut clock_account = clock_account::new(1, 0, 0, 0, 0);
|
||||
keyed_accounts.push(KeyedAccount::new(&pubkey, true, &mut user_account));
|
||||
keyed_accounts.push(KeyedAccount::new(&clock_id, false, &mut clock_account));
|
||||
|
||||
|
@ -177,7 +177,7 @@ fn test_invalid_accounts_len() {
|
|||
Hash::default(),
|
||||
);
|
||||
// move tick height into segment 1
|
||||
let mut clock_account = clock::create_account(1, 0, 0, 0, 0);
|
||||
let mut clock_account = clock_account::new(1, 0, 0, 0, 0);
|
||||
Clock::to(
|
||||
&Clock {
|
||||
slot: 16,
|
||||
|
@ -237,7 +237,7 @@ fn test_submit_mining_ok() {
|
|||
Hash::default(),
|
||||
);
|
||||
// move slot into segment 1
|
||||
let mut clock_account = clock::create_account(1, 0, 0, 0, 0);
|
||||
let mut clock_account = clock_account::new(1, 0, 0, 0, 0);
|
||||
Clock::to(
|
||||
&Clock {
|
||||
slot: DEFAULT_SLOTS_PER_SEGMENT,
|
||||
|
|
|
@ -154,7 +154,7 @@ pub fn process_instruction(
|
|||
vote_state::process_vote(
|
||||
me,
|
||||
&sysvar::slot_hashes::from_keyed_account(&slot_hashes_and_clock[0])?,
|
||||
&sysvar::clock::from_keyed_account(&slot_hashes_and_clock[1])?,
|
||||
&sysvar::clock_account::from_keyed_account(&slot_hashes_and_clock[1])?,
|
||||
other_signers,
|
||||
&vote,
|
||||
)
|
||||
|
@ -188,7 +188,7 @@ mod tests {
|
|||
.iter()
|
||||
.map(|meta| {
|
||||
if sysvar::clock::check_id(&meta.pubkey) {
|
||||
sysvar::clock::create_account(1, 0, 0, 0, 0)
|
||||
sysvar::clock_account::new(1, 0, 0, 0, 0)
|
||||
} else if sysvar::slot_hashes::check_id(&meta.pubkey) {
|
||||
sysvar::slot_hashes::create_account(1, &[])
|
||||
} else {
|
||||
|
|
|
@ -41,7 +41,7 @@ use solana_sdk::{
|
|||
signature::{Keypair, Signature},
|
||||
system_transaction,
|
||||
sysvar::{
|
||||
clock, fees, rewards,
|
||||
clock, clock_account, fees, rewards,
|
||||
slot_hashes::{self, SlotHashes},
|
||||
stake_history,
|
||||
},
|
||||
|
@ -400,7 +400,7 @@ impl Bank {
|
|||
fn update_clock(&self) {
|
||||
self.store_account(
|
||||
&clock::id(),
|
||||
&clock::create_account(
|
||||
&clock_account::new(
|
||||
1,
|
||||
self.slot,
|
||||
get_segment_from_slot(self.slot, self.slots_per_segment),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
pub mod clock;
|
||||
pub mod pubkey;
|
||||
pub mod sysvar;
|
||||
|
||||
// On-chain program modules
|
||||
#[cfg(feature = "program")]
|
||||
|
@ -57,8 +58,6 @@ pub mod system_program;
|
|||
#[cfg(feature = "kitchen_sink")]
|
||||
pub mod system_transaction;
|
||||
#[cfg(feature = "kitchen_sink")]
|
||||
pub mod sysvar;
|
||||
#[cfg(feature = "kitchen_sink")]
|
||||
pub mod timing;
|
||||
#[cfg(feature = "kitchen_sink")]
|
||||
pub mod transaction;
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
//! This account contains the clock slot, epoch, and stakers_epoch
|
||||
//!
|
||||
use crate::account::Account;
|
||||
use crate::sysvar;
|
||||
use bincode::serialized_size;
|
||||
|
||||
pub use crate::clock::{Epoch, Slot};
|
||||
pub use crate::clock::{Epoch, Segment, Slot};
|
||||
|
||||
const ID: [u8; 32] = [
|
||||
6, 167, 213, 23, 24, 199, 116, 201, 40, 86, 99, 152, 105, 29, 94, 182, 139, 94, 184, 163, 155,
|
||||
|
@ -21,59 +18,3 @@ pub struct Clock {
|
|||
pub epoch: Epoch,
|
||||
pub stakers_epoch: Epoch,
|
||||
}
|
||||
|
||||
impl Clock {
|
||||
pub fn from(account: &Account) -> Option<Self> {
|
||||
account.deserialize_data().ok()
|
||||
}
|
||||
pub fn to(&self, account: &mut Account) -> Option<()> {
|
||||
account.serialize_data(self).ok()
|
||||
}
|
||||
|
||||
pub fn size_of() -> usize {
|
||||
serialized_size(&Self::default()).unwrap() as usize
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_account(
|
||||
lamports: u64,
|
||||
slot: Slot,
|
||||
segment: Segment,
|
||||
epoch: Epoch,
|
||||
stakers_epoch: Epoch,
|
||||
) -> Account {
|
||||
Account::new_data(
|
||||
lamports,
|
||||
&Clock {
|
||||
slot,
|
||||
segment,
|
||||
epoch,
|
||||
stakers_epoch,
|
||||
},
|
||||
&sysvar::id(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
use crate::account::KeyedAccount;
|
||||
use crate::clock::Segment;
|
||||
use crate::instruction::InstructionError;
|
||||
|
||||
pub fn from_keyed_account(account: &KeyedAccount) -> Result<Clock, InstructionError> {
|
||||
if !check_id(account.unsigned_key()) {
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
Clock::from(account.account).ok_or(InstructionError::InvalidArgument)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_create_account() {
|
||||
let account = create_account(1, 0, 0, 0, 0);
|
||||
let clock = Clock::from(&account).unwrap();
|
||||
assert_eq!(clock, Clock::default());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
//! Serialize clock support for Account
|
||||
//!
|
||||
use crate::account::Account;
|
||||
use crate::sysvar;
|
||||
use crate::sysvar::clock::{check_id, Clock};
|
||||
use bincode::serialized_size;
|
||||
|
||||
pub use crate::clock::{Epoch, Slot};
|
||||
|
||||
impl Clock {
|
||||
pub fn from(account: &Account) -> Option<Self> {
|
||||
account.deserialize_data().ok()
|
||||
}
|
||||
pub fn to(&self, account: &mut Account) -> Option<()> {
|
||||
account.serialize_data(self).ok()
|
||||
}
|
||||
|
||||
pub fn size_of() -> usize {
|
||||
serialized_size(&Self::default()).unwrap() as usize
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
lamports: u64,
|
||||
slot: Slot,
|
||||
segment: Segment,
|
||||
epoch: Epoch,
|
||||
stakers_epoch: Epoch,
|
||||
) -> Account {
|
||||
Account::new_data(
|
||||
lamports,
|
||||
&Clock {
|
||||
slot,
|
||||
segment,
|
||||
epoch,
|
||||
stakers_epoch,
|
||||
},
|
||||
&sysvar::id(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
use crate::account::KeyedAccount;
|
||||
use crate::clock::Segment;
|
||||
use crate::instruction::InstructionError;
|
||||
|
||||
pub fn from_keyed_account(account: &KeyedAccount) -> Result<Clock, InstructionError> {
|
||||
if !check_id(account.unsigned_key()) {
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
Clock::from(account.account).ok_or(InstructionError::InvalidArgument)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_create_account() {
|
||||
let account = new(1, 0, 0, 0, 0);
|
||||
let clock = Clock::from(&account).unwrap();
|
||||
assert_eq!(clock, Clock::default());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
//! Serialize clock support for AccountInfo
|
||||
//!
|
||||
use crate::account_info::AccountInfo;
|
||||
use crate::sysvar::clock::Clock;
|
||||
use bincode::serialized_size;
|
||||
|
||||
impl Clock {
|
||||
pub fn from(account: &AccountInfo) -> Option<Self> {
|
||||
account.deserialize_data().ok()
|
||||
}
|
||||
pub fn to(&self, account: &mut AccountInfo) -> Option<()> {
|
||||
account.serialize_data(self).ok()
|
||||
}
|
||||
|
||||
pub fn size_of() -> usize {
|
||||
serialized_size(&Self::default()).unwrap() as usize
|
||||
}
|
||||
}
|
|
@ -1,13 +1,25 @@
|
|||
//! named accounts for synthesized data accounts for bank state, etc.
|
||||
//!
|
||||
#[cfg(feature = "kitchen_sink")]
|
||||
use crate::pubkey::Pubkey;
|
||||
|
||||
pub mod clock;
|
||||
|
||||
#[cfg(feature = "program")]
|
||||
pub mod clock_account_info;
|
||||
|
||||
#[cfg(feature = "kitchen_sink")]
|
||||
pub mod clock_account;
|
||||
#[cfg(feature = "kitchen_sink")]
|
||||
pub mod fees;
|
||||
#[cfg(feature = "kitchen_sink")]
|
||||
pub mod rewards;
|
||||
#[cfg(feature = "kitchen_sink")]
|
||||
pub mod slot_hashes;
|
||||
#[cfg(feature = "kitchen_sink")]
|
||||
pub mod stake_history;
|
||||
|
||||
#[cfg(feature = "kitchen_sink")]
|
||||
pub fn is_sysvar_id(id: &Pubkey) -> bool {
|
||||
clock::check_id(id) || fees::check_id(id) || rewards::check_id(id) || slot_hashes::check_id(id)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue