From 1853771930be6bcc42d3a8f20b2a2fa0295b6505 Mon Sep 17 00:00:00 2001 From: Jack May Date: Tue, 10 Sep 2019 18:53:02 -0700 Subject: [PATCH] Add support for SDK sysvar types (#5876) --- Cargo.lock | 8 ++-- core/src/staking_utils.rs | 2 +- programs/bpf/Cargo.toml | 2 +- programs/bpf/build.rs | 2 +- programs/bpf/rust/clock/src/lib.rs | 28 ------------ .../bpf/rust/{clock => sysval}/.gitignore | 0 .../bpf/rust/{clock => sysval}/Cargo.toml | 6 +-- .../bpf/rust/{clock => sysval}/Xargo.toml | 0 programs/bpf/rust/sysval/src/lib.rs | 43 +++++++++++++++++++ programs/bpf/tests/programs.rs | 17 +++++--- programs/bpf_loader_api/Cargo.toml | 2 +- .../stake_tests/tests/stake_instruction.rs | 2 +- .../tests/storage_processor.rs | 2 +- runtime/src/bank.rs | 10 ++--- sdk/src/log.rs | 6 +-- sdk/src/sysvar/fees.rs | 14 ++++-- sdk/src/sysvar/rewards.rs | 15 +++++-- sdk/src/sysvar/slot_hashes.rs | 20 ++++++--- sdk/src/sysvar/stake_history.rs | 20 ++++++--- 19 files changed, 124 insertions(+), 75 deletions(-) delete mode 100644 programs/bpf/rust/clock/src/lib.rs rename programs/bpf/rust/{clock => sysval}/.gitignore (100%) rename programs/bpf/rust/{clock => sysval}/Cargo.toml (82%) rename programs/bpf/rust/{clock => sysval}/Xargo.toml (100%) create mode 100644 programs/bpf/rust/sysval/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index c8f05f7d3..4123b357f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2893,7 +2893,7 @@ dependencies = [ "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)", "solana-logger 0.19.0-pre0", "solana-sdk 0.19.0-pre0", - "solana_rbpf 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "solana_rbpf 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2917,7 +2917,7 @@ dependencies = [ "solana-logger 0.19.0-pre0", "solana-runtime 0.19.0-pre0", "solana-sdk 0.19.0-pre0", - "solana_rbpf 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "solana_rbpf 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4141,7 +4141,7 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5365,7 +5365,7 @@ dependencies = [ "checksum solana_libra_vm_cache_map 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f0abd2cc72c7d76ca9e0764e3f1fa01a01f49b9014a193f2a3fe735a034bf96" "checksum solana_libra_vm_genesis 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4dadfcf5fabfd28d09770d698c618a48d75819f6915bd8bdfa04b93b6e492530" "checksum solana_libra_vm_runtime 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "055a5de29d1b8a2b9f9e20293e07998b8e188164bbe6ac8a09260043f99379aa" -"checksum solana_rbpf 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "31bb26b38c7f84afa1fa266e8fd46ae93bec1ea7253f09a3288dfd118a0086e3" +"checksum solana_rbpf 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "7b5902653b9c19efe7821e1058836554786668438bf2ba048fbce04fb633e0c0" "checksum solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "172382bac9424588d7840732b250faeeef88942e37b6e35317dce98cafdd75b2" "checksum spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" "checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" diff --git a/core/src/staking_utils.rs b/core/src/staking_utils.rs index 5243ce070..d183f34db 100644 --- a/core/src/staking_utils.rs +++ b/core/src/staking_utils.rs @@ -227,7 +227,7 @@ pub(crate) mod tests { let mut result: Vec<_> = epoch_stakes_and_lockouts(&bank, next_stakers_epoch); result.sort(); let stake_history = - StakeHistory::from(&bank.get_account(&stake_history::id()).unwrap()).unwrap(); + StakeHistory::from_account(&bank.get_account(&stake_history::id()).unwrap()).unwrap(); let mut expected = vec![ (leader_stake.stake(bank.epoch(), Some(&stake_history)), None), (other_stake.stake(bank.epoch(), Some(&stake_history)), None), diff --git a/programs/bpf/Cargo.toml b/programs/bpf/Cargo.toml index 325fba871..82dfe66e1 100644 --- a/programs/bpf/Cargo.toml +++ b/programs/bpf/Cargo.toml @@ -26,7 +26,7 @@ solana-bpf-loader-api = { path = "../bpf_loader_api", version = "0.19.0-pre0" } solana-logger = { path = "../../logger", version = "0.19.0-pre0" } solana-runtime = { path = "../../runtime", version = "0.19.0-pre0" } solana-sdk = { path = "../../sdk", version = "0.19.0-pre0" } -solana_rbpf = "=0.1.15" +solana_rbpf = "=0.1.16" [[bench]] name = "bpf_loader" diff --git a/programs/bpf/build.rs b/programs/bpf/build.rs index 8ba4b5470..a546b15db 100644 --- a/programs/bpf/build.rs +++ b/programs/bpf/build.rs @@ -70,7 +70,6 @@ fn main() { let rust_programs = [ "128bit", "alloc", - "clock", "dep_crate", "iter", "many_args", @@ -78,6 +77,7 @@ fn main() { "noop", "panic", "param_passing", + "sysval", ]; for program in rust_programs.iter() { println!( diff --git a/programs/bpf/rust/clock/src/lib.rs b/programs/bpf/rust/clock/src/lib.rs deleted file mode 100644 index e6bda0d94..000000000 --- a/programs/bpf/rust/clock/src/lib.rs +++ /dev/null @@ -1,28 +0,0 @@ -//! @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_account_info(&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 -} diff --git a/programs/bpf/rust/clock/.gitignore b/programs/bpf/rust/sysval/.gitignore similarity index 100% rename from programs/bpf/rust/clock/.gitignore rename to programs/bpf/rust/sysval/.gitignore diff --git a/programs/bpf/rust/clock/Cargo.toml b/programs/bpf/rust/sysval/Cargo.toml similarity index 82% rename from programs/bpf/rust/clock/Cargo.toml rename to programs/bpf/rust/sysval/Cargo.toml index 67351af4f..7e8dca0bb 100644 --- a/programs/bpf/rust/clock/Cargo.toml +++ b/programs/bpf/rust/sysval/Cargo.toml @@ -2,9 +2,9 @@ # Note: This crate must be built using build.sh [package] -name = "solana-bpf-rust-clock" +name = "solana-bpf-rust-sysval" version = "0.19.0-pre0" -description = "Solana BPF clock sysvar test" +description = "Solana BPF sysvar test" authors = ["Solana Maintainers "] repository = "https://github.com/solana-labs/solana" license = "Apache-2.0" @@ -23,4 +23,4 @@ members = [] [lib] crate-type = ["cdylib"] -name = "solana_bpf_rust_clock" +name = "solana_bpf_rust_sysval" diff --git a/programs/bpf/rust/clock/Xargo.toml b/programs/bpf/rust/sysval/Xargo.toml similarity index 100% rename from programs/bpf/rust/clock/Xargo.toml rename to programs/bpf/rust/sysval/Xargo.toml diff --git a/programs/bpf/rust/sysval/src/lib.rs b/programs/bpf/rust/sysval/src/lib.rs new file mode 100644 index 000000000..9ff75f088 --- /dev/null +++ b/programs/bpf/rust/sysval/src/lib.rs @@ -0,0 +1,43 @@ +//! @brief Example Rust-based BPF program that tests sysval use + +extern crate solana_sdk; +use solana_sdk::{ + account_info::AccountInfo, + clock::{get_segment_from_slot, DEFAULT_SLOTS_PER_EPOCH, DEFAULT_SLOTS_PER_SEGMENT}, + entrypoint, + entrypoint::SUCCESS, + pubkey::Pubkey, + sysvar::{ + clock::Clock, fees::Fees, rewards::Rewards, slot_hashes::SlotHashes, + stake_history::StakeHistory, + }, +}; + +entrypoint!(process_instruction); +fn process_instruction(_program_id: &Pubkey, accounts: &mut [AccountInfo], _data: &[u8]) -> u32 { + // Clock + let clock = Clock::from_account_info(&accounts[2]).unwrap(); + assert_eq!(clock.slot, DEFAULT_SLOTS_PER_EPOCH + 1); + assert_eq!( + clock.segment, + get_segment_from_slot(clock.slot, DEFAULT_SLOTS_PER_SEGMENT) + ); + + // Fees + let fees = Fees::from_account_info(&accounts[3]).unwrap(); + let burn = fees.fee_calculator.burn(42); + assert_eq!(burn, (21, 21)); + + // Rewards + let _ = Rewards::from_account_info(&accounts[4]).unwrap(); + + // Slot Hashes + let slot_hashes = SlotHashes::from_account_info(&accounts[5]).unwrap(); + assert_eq!(slot_hashes.len(), 1); + + // Stake History + let stake_history = StakeHistory::from_account_info(&accounts[6]).unwrap(); + assert_eq!(stake_history.len(), 1); + + SUCCESS +} diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 84480ae90..fb420f14e 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -79,10 +79,11 @@ mod bpf { use super::*; use solana_sdk::bpf_loader; use solana_sdk::client::SyncClient; + use solana_sdk::clock::DEFAULT_SLOTS_PER_EPOCH; use solana_sdk::instruction::{AccountMeta, Instruction}; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; - use solana_sdk::sysvar::clock; + use solana_sdk::sysvar::{clock, fees, rewards, slot_hashes, stake_history}; use std::io::Read; use std::sync::Arc; @@ -93,7 +94,6 @@ 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), @@ -101,6 +101,7 @@ mod bpf { ("solana_bpf_rust_noop", true), ("solana_bpf_rust_panic", false), ("solana_bpf_rust_param_passing", true), + ("solana_bpf_rust_sysval", true), ]; for program in programs.iter() { let filename = create_bpf_path(program.0); @@ -110,13 +111,15 @@ mod bpf { file.read_to_end(&mut elf).unwrap(); let GenesisBlockInfo { - genesis_block, + mut genesis_block, mint_keypair, .. } = create_genesis_block(50); + genesis_block.epoch_warmup = false; 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); + // Create bank with specific slot, used by solana_bpf_rust_sysvar test + let bank = + Bank::new_from_parent(&bank, &Pubkey::default(), DEFAULT_SLOTS_PER_EPOCH + 1); let bank_client = BankClient::new(bank); // Call user program @@ -125,6 +128,10 @@ mod bpf { AccountMeta::new(mint_keypair.pubkey(), true), AccountMeta::new(Keypair::new().pubkey(), false), AccountMeta::new(clock::id(), false), + AccountMeta::new(fees::id(), false), + AccountMeta::new(rewards::id(), false), + AccountMeta::new(slot_hashes::id(), false), + AccountMeta::new(stake_history::id(), false), ]; let instruction = Instruction::new(program_id, &1u8, account_metas); let result = bank_client.send_instruction(&mint_keypair, instruction); diff --git a/programs/bpf_loader_api/Cargo.toml b/programs/bpf_loader_api/Cargo.toml index 5bbb83960..f34e90a47 100644 --- a/programs/bpf_loader_api/Cargo.toml +++ b/programs/bpf_loader_api/Cargo.toml @@ -16,7 +16,7 @@ log = "0.4.8" serde = "1.0.100" solana-logger = { path = "../../logger", version = "0.19.0-pre0" } solana-sdk = { path = "../../sdk", version = "0.19.0-pre0" } -solana_rbpf = "=0.1.15" +solana_rbpf = "=0.1.16" [lib] crate-type = ["lib"] diff --git a/programs/stake_tests/tests/stake_instruction.rs b/programs/stake_tests/tests/stake_instruction.rs index af4cbf6aa..73ac528aa 100644 --- a/programs/stake_tests/tests/stake_instruction.rs +++ b/programs/stake_tests/tests/stake_instruction.rs @@ -147,7 +147,7 @@ fn test_stake_account_delegate() { let rewards_account = bank .get_account(&sysvar::rewards::id()) .expect("account not found"); - assert_matches!(Rewards::from(&rewards_account), Some(_)); + assert_matches!(Rewards::from_account(&rewards_account), Some(_)); // Redeem the credit let bank_client = BankClient::new_shared(&bank); diff --git a/programs/storage_program/tests/storage_processor.rs b/programs/storage_program/tests/storage_processor.rs index 107dc228c..da585ef23 100644 --- a/programs/storage_program/tests/storage_processor.rs +++ b/programs/storage_program/tests/storage_processor.rs @@ -401,7 +401,7 @@ fn test_validate_mining() { let rewards = bank .get_account(&rewards::id()) - .map(|account| Rewards::from(&account).unwrap()) + .map(|account| Rewards::from_account(&account).unwrap()) .unwrap(); let message = Message::new_with_payer( vec![storage_instruction::claim_reward( diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 4a187a747..678beb063 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -415,9 +415,9 @@ impl Bank { .get_account(&slot_hashes::id()) .unwrap_or_else(|| slot_hashes::create_account(1, &[])); - let mut slot_hashes = SlotHashes::from(&account).unwrap(); + let mut slot_hashes = SlotHashes::from_account(&account).unwrap(); slot_hashes.add(self.slot(), self.hash()); - slot_hashes.to(&mut account).unwrap(); + slot_hashes.to_account(&mut account).unwrap(); self.store_account(&slot_hashes::id(), &account); } @@ -484,7 +484,7 @@ impl Bank { mut validator_point_value: f64, mut storage_point_value: f64, ) -> (f64, f64) { - let rewards = rewards::Rewards::from( + let rewards = rewards::Rewards::from_account( &self .get_account(&rewards::id()) .unwrap_or_else(|| rewards::create_account(1, 0.0, 0.0)), @@ -1620,7 +1620,7 @@ mod tests { let rewards = bank1 .get_account(&rewards::id()) - .map(|account| Rewards::from(&account).unwrap()) + .map(|account| Rewards::from_account(&account).unwrap()) .unwrap(); assert!( @@ -2755,7 +2755,7 @@ mod tests { let bank = Arc::new(Bank::new(&genesis_block)); let fees_account = bank.get_account(&fees::id()).unwrap(); - let fees = Fees::from(&fees_account).unwrap(); + let fees = Fees::from_account(&fees_account).unwrap(); assert_eq!( bank.fee_calculator.lamports_per_signature, fees.fee_calculator.lamports_per_signature diff --git a/sdk/src/log.rs b/sdk/src/log.rs index 27f31c6be..c72371d29 100644 --- a/sdk/src/log.rs +++ b/sdk/src/log.rs @@ -60,7 +60,7 @@ pub fn sol_log_slice(slice: &[u8]) { /// Prints the hexadecimal representation of the program's input parameters /// -/// @param ka - A pointer to an array of `SolKeyedAccounts` to print +/// @param ka - A pointer to an array of `AccountInfo` to print /// @param data - A pointer to the instruction data to print #[allow(dead_code)] pub fn sol_log_params(accounts: &[AccountInfo], data: &[u8]) { @@ -73,8 +73,8 @@ pub fn sol_log_params(accounts: &[AccountInfo], data: &[u8]) { account.key.log(); sol_log("- Lamports"); sol_log_64(0, 0, 0, 0, *account.lamports); - sol_log("- AccountData"); - sol_log_slice(account.data); + sol_log("- Account data length"); + sol_log_64(0, 0, 0, 0, account.data.len() as u64); sol_log("- Owner"); account.owner.log(); } diff --git a/sdk/src/sysvar/fees.rs b/sdk/src/sysvar/fees.rs index 77d19574c..f55cfee6d 100644 --- a/sdk/src/sysvar/fees.rs +++ b/sdk/src/sysvar/fees.rs @@ -1,6 +1,7 @@ //! This account contains the current cluster fees //! use crate::account::Account; +use crate::account_info::AccountInfo; use crate::fee_calculator::FeeCalculator; use crate::sysvar; use bincode::serialized_size; @@ -20,13 +21,18 @@ pub struct Fees { } impl Fees { - pub fn from(account: &Account) -> Option { + pub fn from_account(account: &Account) -> Option { account.deserialize_data().ok() } - pub fn to(&self, account: &mut Account) -> Option<()> { + pub fn to_account(&self, account: &mut Account) -> Option<()> { + account.serialize_data(self).ok() + } + pub fn from_account_info(account: &AccountInfo) -> Option { + account.deserialize_data().ok() + } + pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> { account.serialize_data(self).ok() } - pub fn size_of() -> usize { serialized_size(&Fees::default()).unwrap() as usize } @@ -51,7 +57,7 @@ mod tests { fn test_fees_create_account() { let lamports = 42; let account = create_account(lamports, &FeeCalculator::default()); - let fees = Fees::from(&account).unwrap(); + let fees = Fees::from_account(&account).unwrap(); assert_eq!(fees.fee_calculator, FeeCalculator::default()); } } diff --git a/sdk/src/sysvar/rewards.rs b/sdk/src/sysvar/rewards.rs index b5f294860..adcdd8607 100644 --- a/sdk/src/sysvar/rewards.rs +++ b/sdk/src/sysvar/rewards.rs @@ -1,6 +1,7 @@ //! This account contains the current cluster rewards point values //! use crate::account::Account; +use crate::account_info::AccountInfo; use crate::sysvar; use bincode::serialized_size; @@ -20,10 +21,16 @@ pub struct Rewards { } impl Rewards { - pub fn from(account: &Account) -> Option { + pub fn from_account(account: &Account) -> Option { account.deserialize_data().ok() } - pub fn to(&self, account: &mut Account) -> Option<()> { + pub fn to_account(&self, account: &mut Account) -> Option<()> { + account.serialize_data(self).ok() + } + pub fn from_account_info(account: &AccountInfo) -> Option { + account.deserialize_data().ok() + } + pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> { account.serialize_data(self).ok() } pub fn size_of() -> usize { @@ -54,7 +61,7 @@ pub fn from_keyed_account(account: &KeyedAccount) -> Result); impl SlotHashes { - pub fn from(account: &Account) -> Option { + pub fn from_account(account: &Account) -> Option { account.deserialize_data().ok() } - pub fn to(&self, account: &mut Account) -> Option<()> { + pub fn to_account(&self, account: &mut Account) -> Option<()> { + account.serialize_data(self).ok() + } + pub fn from_account_info(account: &AccountInfo) -> Option { + account.deserialize_data().ok() + } + pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> { account.serialize_data(self).ok() } - pub fn size_of() -> usize { serialized_size(&SlotHashes(vec![(0, Hash::default()); MAX_SLOT_HASHES])).unwrap() as usize } @@ -62,7 +68,9 @@ impl Deref for SlotHashes { pub fn create_account(lamports: u64, slot_hashes: &[SlotHash]) -> Account { let mut account = Account::new(lamports, SlotHashes::size_of(), &sysvar::id()); - SlotHashes::new(slot_hashes).to(&mut account).unwrap(); + SlotHashes::new(slot_hashes) + .to_account(&mut account) + .unwrap(); account } @@ -72,7 +80,7 @@ pub fn from_keyed_account(account: &KeyedAccount) -> Result); impl StakeHistory { - pub fn from(account: &Account) -> Option { + pub fn from_account(account: &Account) -> Option { account.deserialize_data().ok() } - pub fn to(&self, account: &mut Account) -> Option<()> { + pub fn to_account(&self, account: &mut Account) -> Option<()> { + account.serialize_data(self).ok() + } + pub fn from_account_info(account: &AccountInfo) -> Option { + account.deserialize_data().ok() + } + pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> { account.serialize_data(self).ok() } - pub fn size_of() -> usize { serialized_size(&StakeHistory(vec![ (0, StakeHistoryEntry::default()); @@ -67,7 +73,7 @@ impl Deref for StakeHistory { pub fn create_account(lamports: u64, stake_history: &StakeHistory) -> Account { let mut account = Account::new(lamports, StakeHistory::size_of(), &sysvar::id()); - stake_history.to(&mut account).unwrap(); + stake_history.to_account(&mut account).unwrap(); account } @@ -77,7 +83,7 @@ pub fn from_keyed_account(account: &KeyedAccount) -> Result