diff --git a/programs/bpf/rust/noop/src/lib.rs b/programs/bpf/rust/noop/src/lib.rs index eb2ba83023..0c19dffb49 100644 --- a/programs/bpf/rust/noop/src/lib.rs +++ b/programs/bpf/rust/noop/src/lib.rs @@ -25,8 +25,6 @@ fn process_instruction( info: &SolClusterInfo, data: &[u8], ) -> bool { - sol_log("Tick height:"); - sol_log_64(info.tick_height, 0, 0, 0, 0); sol_log("Program identifier:"); sol_log_key(&info.program_id); diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 4fe2f88851..47ad938cf5 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -233,7 +233,6 @@ fn serialize_parameters( program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], data: &[u8], - tick_height: u64, ) -> Vec { assert_eq!(32, mem::size_of::()); @@ -252,7 +251,6 @@ fn serialize_parameters( } v.write_u64::(data.len() as u64).unwrap(); v.write_all(data).unwrap(); - v.write_u64::(tick_height).unwrap(); v.write_all(program_id.as_ref()).unwrap(); v } @@ -281,7 +279,6 @@ fn entrypoint( program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], tx_data: &[u8], - tick_height: u64, ) -> Result<(), InstructionError> { solana_logger::setup(); @@ -296,7 +293,7 @@ fn entrypoint( return Err(InstructionError::GenericError); } }; - let mut v = serialize_parameters(program_id, params, &tx_data, tick_height); + let mut v = serialize_parameters(program_id, params, &tx_data); match vm.execute_program(v.as_mut_slice(), &[], &[heap_region]) { Ok(status) => { diff --git a/programs/budget_api/src/budget_processor.rs b/programs/budget_api/src/budget_processor.rs index dddbce843f..6b7b8cf938 100644 --- a/programs/budget_api/src/budget_processor.rs +++ b/programs/budget_api/src/budget_processor.rs @@ -74,7 +74,6 @@ pub fn process_instruction( _program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], data: &[u8], - _tick_height: u64, ) -> Result<(), InstructionError> { let instruction = deserialize(data).map_err(|err| { info!("Invalid transaction data: {:?} {:?}", data, err); diff --git a/programs/config_api/src/config_processor.rs b/programs/config_api/src/config_processor.rs index bc1f4da36a..ffe157696e 100644 --- a/programs/config_api/src/config_processor.rs +++ b/programs/config_api/src/config_processor.rs @@ -9,7 +9,6 @@ pub fn process_instruction( _program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], data: &[u8], - _tick_height: u64, ) -> Result<(), InstructionError> { if keyed_accounts[0].signer_key().is_none() { error!("account[0].signer_key().is_none()"); diff --git a/programs/exchange_api/src/exchange_processor.rs b/programs/exchange_api/src/exchange_processor.rs index 58d7871bd8..e17782d0f0 100644 --- a/programs/exchange_api/src/exchange_processor.rs +++ b/programs/exchange_api/src/exchange_processor.rs @@ -429,7 +429,6 @@ pub fn process_instruction( _program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], data: &[u8], - _tick_height: u64, ) -> Result<(), InstructionError> { solana_logger::setup(); diff --git a/programs/failure_program/src/lib.rs b/programs/failure_program/src/lib.rs index afb5abf98e..aa0cc0ddb4 100644 --- a/programs/failure_program/src/lib.rs +++ b/programs/failure_program/src/lib.rs @@ -8,7 +8,6 @@ fn entrypoint( _program_id: &Pubkey, _keyed_accounts: &mut [KeyedAccount], _data: &[u8], - _tick_height: u64, ) -> Result<(), InstructionError> { Err(InstructionError::GenericError) } diff --git a/programs/noop_program/src/lib.rs b/programs/noop_program/src/lib.rs index 707257e07f..f75c861cb8 100644 --- a/programs/noop_program/src/lib.rs +++ b/programs/noop_program/src/lib.rs @@ -9,12 +9,10 @@ fn entrypoint( program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], data: &[u8], - tick_height: u64, ) -> Result<(), InstructionError> { solana_logger::setup(); trace!("noop: program_id: {:?}", program_id); trace!("noop: keyed_accounts: {:#?}", keyed_accounts); trace!("noop: data: {:?}", data); - trace!("noop: tick_height: {:?}", tick_height); Ok(()) } diff --git a/programs/stake_api/src/stake_instruction.rs b/programs/stake_api/src/stake_instruction.rs index 2990dce648..947a9f1e33 100644 --- a/programs/stake_api/src/stake_instruction.rs +++ b/programs/stake_api/src/stake_instruction.rs @@ -122,7 +122,6 @@ pub fn process_instruction( _program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], data: &[u8], - _tick_height: u64, ) -> Result<(), InstructionError> { solana_logger::setup(); @@ -190,12 +189,7 @@ mod tests { .zip(accounts.iter_mut()) .map(|(meta, account)| KeyedAccount::new(&meta.pubkey, meta.is_signer, account)) .collect(); - super::process_instruction( - &Pubkey::default(), - &mut keyed_accounts, - &instruction.data, - 0, - ) + super::process_instruction(&Pubkey::default(), &mut keyed_accounts, &instruction.data) } } @@ -234,7 +228,6 @@ mod tests { &mut Account::default(), )], &serialize(&StakeInstruction::DelegateStake).unwrap(), - 0, ), Err(InstructionError::InvalidInstructionData), ); @@ -248,7 +241,6 @@ mod tests { KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()), ], &serialize(&StakeInstruction::DelegateStake).unwrap(), - 0, ), Err(InstructionError::InvalidInstructionData), ); @@ -262,7 +254,6 @@ mod tests { KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()), ], &serialize(&StakeInstruction::RedeemVoteCredits).unwrap(), - 0, ), Err(InstructionError::InvalidInstructionData), ); @@ -277,7 +268,6 @@ mod tests { KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()), ], &serialize(&StakeInstruction::DelegateStake).unwrap(), - 0, ), Err(InstructionError::InvalidAccountData), ); @@ -293,7 +283,6 @@ mod tests { KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()), ], &serialize(&StakeInstruction::RedeemVoteCredits).unwrap(), - 0, ), Err(InstructionError::InvalidAccountData), ); diff --git a/programs/storage_api/src/storage_instruction.rs b/programs/storage_api/src/storage_instruction.rs index 569f2ac2a2..2b317afa9d 100644 --- a/programs/storage_api/src/storage_instruction.rs +++ b/programs/storage_api/src/storage_instruction.rs @@ -5,6 +5,7 @@ use solana_sdk::hash::Hash; use solana_sdk::instruction::{AccountMeta, Instruction}; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::Signature; +use solana_sdk::syscall::tick_height; use solana_sdk::system_instruction; use std::collections::HashMap; @@ -118,7 +119,10 @@ pub fn mining_proof( signature, proof_index, }; - let account_metas = vec![AccountMeta::new(*storage_pubkey, true)]; + let account_metas = vec![ + AccountMeta::new(*storage_pubkey, true), + AccountMeta::new(tick_height::id(), false), + ]; Instruction::new(id(), &storage_instruction, account_metas) } @@ -131,7 +135,10 @@ pub fn advertise_recent_blockhash( hash: storage_hash, slot, }; - let account_metas = vec![AccountMeta::new(*storage_pubkey, true)]; + let account_metas = vec![ + AccountMeta::new(*storage_pubkey, true), + AccountMeta::new(tick_height::id(), false), + ]; Instruction::new(id(), &storage_instruction, account_metas) } @@ -159,6 +166,7 @@ pub fn claim_reward( let account_metas = vec![ AccountMeta::new(*storage_pubkey, false), AccountMeta::new(*mining_pool_pubkey, false), + AccountMeta::new(tick_height::id(), false), ]; Instruction::new(id(), &storage_instruction, account_metas) } diff --git a/programs/storage_api/src/storage_processor.rs b/programs/storage_api/src/storage_processor.rs index 2f0ea35c5f..d8bf70357e 100644 --- a/programs/storage_api/src/storage_processor.rs +++ b/programs/storage_api/src/storage_processor.rs @@ -6,13 +6,13 @@ use crate::storage_instruction::StorageInstruction; use solana_sdk::account::KeyedAccount; use solana_sdk::instruction::InstructionError; use solana_sdk::pubkey::Pubkey; +use solana_sdk::syscall::tick_height::TickHeight; use solana_sdk::timing::DEFAULT_TICKS_PER_SLOT; pub fn process_instruction( _program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], data: &[u8], - tick_height: u64, ) -> Result<(), InstructionError> { solana_logger::setup(); @@ -45,10 +45,11 @@ pub fn process_instruction( signature, .. } => { - if me_unsigned || !rest.is_empty() { + if me_unsigned || rest.len() != 1 { // This instruction must be signed by `me` Err(InstructionError::InvalidArgument)?; } + let tick_height = TickHeight::from(&rest[0].account).unwrap(); storage_account.submit_mining_proof( sha_state, slot, @@ -57,10 +58,11 @@ pub fn process_instruction( ) } StorageInstruction::AdvertiseStorageRecentBlockhash { hash, slot } => { - if me_unsigned || !rest.is_empty() { + if me_unsigned || rest.len() != 1 { // This instruction must be signed by `me` Err(InstructionError::InvalidArgument)?; } + let tick_height = TickHeight::from(&rest[0].account).unwrap(); storage_account.advertise_storage_recent_blockhash( hash, slot, @@ -68,9 +70,10 @@ pub fn process_instruction( ) } StorageInstruction::ClaimStorageReward { slot } => { - if rest.len() != 1 { + if rest.len() != 2 { Err(InstructionError::InvalidArgument)?; } + let tick_height = TickHeight::from(&rest[1].account).unwrap(); storage_account.claim_storage_reward( &mut rest[0], slot, @@ -114,6 +117,7 @@ mod tests { use solana_sdk::message::Message; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil, Signature}; + use solana_sdk::syscall::tick_height; use std::collections::HashMap; use std::sync::Arc; @@ -122,7 +126,6 @@ mod tests { fn test_instruction( ix: &Instruction, program_accounts: &mut [Account], - tick_height: u64, ) -> Result<(), InstructionError> { let mut keyed_accounts: Vec<_> = ix .accounts @@ -133,7 +136,7 @@ mod tests { }) .collect(); - let ret = process_instruction(&id(), &mut keyed_accounts, &ix.data, tick_height); + let ret = process_instruction(&id(), &mut keyed_accounts, &ix.data); info!("ret: {:?}", ret); ret } @@ -159,11 +162,10 @@ mod tests { ); // the proof is for slot 16, which is in segment 0, need to move the tick height into segment 2 let ticks_till_next_segment = TICKS_IN_SEGMENT * 2; + let mut tick_account = tick_height::create_account(1); + TickHeight::to(ticks_till_next_segment, &mut tick_account); - assert_eq!( - test_instruction(&ix, &mut [account], ticks_till_next_segment), - Ok(()) - ); + assert_eq!(test_instruction(&ix, &mut [account, tick_account]), Ok(())); } #[test] @@ -171,15 +173,18 @@ mod tests { let pubkey = Pubkey::new_rand(); let mut accounts = [(pubkey, Account::default())]; let mut keyed_accounts = create_keyed_accounts(&mut accounts); - assert!(process_instruction(&id(), &mut keyed_accounts, &[], 42).is_err()); + assert!(process_instruction(&id(), &mut keyed_accounts, &[]).is_err()); } #[test] fn test_serialize_overflow() { let pubkey = Pubkey::new_rand(); + let tick_pubkey = Pubkey::new_rand(); let mut keyed_accounts = Vec::new(); let mut user_account = Account::default(); + let mut tick_account = tick_height::create_account(1); keyed_accounts.push(KeyedAccount::new(&pubkey, true, &mut user_account)); + keyed_accounts.push(KeyedAccount::new(&tick_pubkey, false, &mut tick_account)); let ix = storage_instruction::advertise_recent_blockhash( &pubkey, @@ -188,7 +193,7 @@ mod tests { ); assert_eq!( - process_instruction(&id(), &mut keyed_accounts, &ix.data, 42), + process_instruction(&id(), &mut keyed_accounts, &ix.data), Err(InstructionError::InvalidAccountData) ); } @@ -202,12 +207,14 @@ mod tests { storage_instruction::mining_proof(&pubkey, Hash::default(), 0, Signature::default(), 0); // move tick height into segment 1 let ticks_till_next_segment = TICKS_IN_SEGMENT + 1; + let mut tick_account = tick_height::create_account(1); + TickHeight::to(ticks_till_next_segment, &mut tick_account); - assert!(test_instruction(&ix, &mut accounts, ticks_till_next_segment).is_err()); + assert!(test_instruction(&ix, &mut accounts).is_err()); - let mut accounts = [Account::default(), Account::default(), Account::default()]; + let mut accounts = [Account::default(), tick_account, Account::default()]; - assert!(test_instruction(&ix, &mut accounts, ticks_till_next_segment).is_err()); + assert!(test_instruction(&ix, &mut accounts).is_err()); } #[test] @@ -222,17 +229,17 @@ mod tests { storage_instruction::mining_proof(&pubkey, Hash::default(), 0, Signature::default(), 0); // submitting a proof for a slot in the past, so this should fail - assert!(test_instruction(&ix, &mut accounts, 0).is_err()); + assert!(test_instruction(&ix, &mut accounts).is_err()); } #[test] fn test_submit_mining_ok() { solana_logger::setup(); let pubkey = Pubkey::new_rand(); - let mut accounts = [Account::default(), Account::default()]; - accounts[0].data.resize(STORAGE_ACCOUNT_SPACE as usize, 0); + let mut account = Account::default(); + account.data.resize(STORAGE_ACCOUNT_SPACE as usize, 0); { - let mut storage_account = StorageAccount::new(&mut accounts[0]); + let mut storage_account = StorageAccount::new(&mut account); storage_account.initialize_replicator_storage().unwrap(); } @@ -240,11 +247,10 @@ mod tests { storage_instruction::mining_proof(&pubkey, Hash::default(), 0, Signature::default(), 0); // move tick height into segment 1 let ticks_till_next_segment = TICKS_IN_SEGMENT + 1; + let mut tick_account = tick_height::create_account(1); + TickHeight::to(ticks_till_next_segment, &mut tick_account); - assert_matches!( - test_instruction(&ix, &mut accounts, ticks_till_next_segment), - Ok(_) - ); + assert_matches!(test_instruction(&ix, &mut [account, tick_account]), Ok(_)); } #[test] diff --git a/programs/token_api/src/token_processor.rs b/programs/token_api/src/token_processor.rs index 4dbdbdb3d1..7871f27547 100644 --- a/programs/token_api/src/token_processor.rs +++ b/programs/token_api/src/token_processor.rs @@ -8,7 +8,6 @@ pub fn process_instruction( program_id: &Pubkey, info: &mut [KeyedAccount], input: &[u8], - _tick_height: u64, ) -> Result<(), InstructionError> { solana_logger::setup(); diff --git a/programs/vote_api/src/vote_instruction.rs b/programs/vote_api/src/vote_instruction.rs index 0840cb3e18..d8bd5f2654 100644 --- a/programs/vote_api/src/vote_instruction.rs +++ b/programs/vote_api/src/vote_instruction.rs @@ -95,7 +95,6 @@ pub fn process_instruction( _program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], data: &[u8], - _tick_height: u64, ) -> Result<(), InstructionError> { solana_logger::setup(); @@ -136,7 +135,7 @@ mod tests { #[test] fn test_vote_process_instruction_decode_bail() { assert_eq!( - super::process_instruction(&Pubkey::default(), &mut [], &[], 0,), + super::process_instruction(&Pubkey::default(), &mut [], &[],), Err(InstructionError::InvalidInstructionData), ); } @@ -153,12 +152,7 @@ mod tests { .zip(accounts.iter_mut()) .map(|(meta, account)| KeyedAccount::new(&meta.pubkey, meta.is_signer, account)) .collect(); - super::process_instruction( - &Pubkey::default(), - &mut keyed_accounts, - &instruction.data, - 0, - ) + super::process_instruction(&Pubkey::default(), &mut keyed_accounts, &instruction.data) } } diff --git a/runtime/benches/bank.rs b/runtime/benches/bank.rs index 0df9b56603..79f6e29deb 100644 --- a/runtime/benches/bank.rs +++ b/runtime/benches/bank.rs @@ -29,7 +29,6 @@ fn process_instruction( _program_id: &Pubkey, _keyed_accounts: &mut [KeyedAccount], _data: &[u8], - _tick_height: u64, ) -> Result<(), InstructionError> { Ok(()) } diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index f231ea1cc6..020091140a 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -29,6 +29,7 @@ use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, Signature}; use solana_sdk::syscall::fees::{self, Fees}; use solana_sdk::syscall::slot_hashes::{self, SlotHashes}; +use solana_sdk::syscall::tick_height::{self, TickHeight}; use solana_sdk::system_transaction; use solana_sdk::timing::{duration_as_ms, duration_as_us, MAX_RECENT_BLOCKHASHES}; use solana_sdk::transaction::{Result, Transaction, TransactionError}; @@ -365,6 +366,16 @@ impl Bank { self.store(&fees::id(), &account); } + fn update_tick_height(&self) { + let mut account = self + .get_account(&tick_height::id()) + .unwrap_or_else(|| tick_height::create_account(1)); + + TickHeight::to(self.tick_height(), &mut account).unwrap(); + + self.store(&tick_height::id(), &account); + } + fn set_hash(&self) -> bool { let mut hash = self.hash.write().unwrap(); @@ -566,6 +577,8 @@ impl Bank { }; inc_new_counter_debug!("bank-register_tick-registered", 1); + self.update_tick_height(); + // Register a new block hash if at the last tick in the slot if current_tick_height % self.ticks_per_slot == self.ticks_per_slot - 1 { self.blockhash_queue.write().unwrap().register_hash(hash); @@ -804,21 +817,20 @@ impl Bank { &mut error_counters, ); let mut loaded_accounts = self.load_accounts(txs, sig_results, &mut error_counters); - let tick_height = self.tick_height(); let load_elapsed = now.elapsed(); let now = Instant::now(); - let executed: Vec> = - loaded_accounts - .iter_mut() - .zip(txs.iter()) - .map(|(accs, tx)| match accs { - Err(e) => Err(e.clone()), - Ok((ref mut accounts, ref mut loaders)) => self - .message_processor - .process_message(tx.message(), loaders, accounts, tick_height), - }) - .collect(); + let executed: Vec> = loaded_accounts + .iter_mut() + .zip(txs.iter()) + .map(|(accs, tx)| match accs { + Err(e) => Err(e.clone()), + Ok((ref mut accounts, ref mut loaders)) => { + self.message_processor + .process_message(tx.message(), loaders, accounts) + } + }) + .collect(); let execution_elapsed = now.elapsed(); @@ -2172,6 +2184,21 @@ mod tests { assert_eq!(fees.fee_calculator.lamports_per_signature, 12345); } + #[test] + fn test_bank_tick_height_account() { + let (genesis_block, _) = create_genesis_block(1); + let bank = Bank::new(&genesis_block); + + for i in 0..10 { + bank.register_tick(&hash::hash(format!("hashing {}", i).as_bytes())); + } + + let tick_account = bank.get_account(&tick_height::id()).unwrap(); + let tick_height = TickHeight::from(&tick_account).unwrap(); + assert_eq!(bank.tick_height(), tick_height); + assert_eq!(tick_height, 10); + } + #[test] fn test_is_delta_with_no_committables() { let (genesis_block, mint_keypair) = create_genesis_block(8000); diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index e6c565f65f..e19f0a194b 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -82,7 +82,7 @@ fn verify_instruction( } pub type ProcessInstruction = - fn(&Pubkey, &mut [KeyedAccount], &[u8], u64) -> Result<(), InstructionError>; + fn(&Pubkey, &mut [KeyedAccount], &[u8]) -> Result<(), InstructionError>; pub type SymbolCache = RwLock, Symbol>>; @@ -127,7 +127,6 @@ impl MessageProcessor { instruction: &CompiledInstruction, executable_accounts: &mut [(Pubkey, Account)], program_accounts: &mut [&mut Account], - tick_height: u64, ) -> Result<(), InstructionError> { let program_id = instruction.program_id(&message.account_keys); @@ -151,7 +150,6 @@ impl MessageProcessor { &program_id, &mut keyed_accounts[1..], &instruction.data, - tick_height, ); } } @@ -160,7 +158,6 @@ impl MessageProcessor { &program_id, &mut keyed_accounts, &instruction.data, - tick_height, &self.symbol_cache, ) } @@ -175,7 +172,6 @@ impl MessageProcessor { instruction: &CompiledInstruction, executable_accounts: &mut [(Pubkey, Account)], program_accounts: &mut [&mut Account], - tick_height: u64, ) -> Result<(), InstructionError> { let program_id = instruction.program_id(&message.account_keys); // TODO: the runtime should be checking read/write access to memory @@ -186,13 +182,7 @@ impl MessageProcessor { .map(|a| (a.owner, a.lamports, a.data.clone())) .collect(); - self.process_instruction( - message, - instruction, - executable_accounts, - program_accounts, - tick_height, - )?; + self.process_instruction(message, instruction, executable_accounts, program_accounts)?; // Verify the instruction for ((pre_program_id, pre_lamports, pre_data), post_account) in @@ -222,7 +212,6 @@ impl MessageProcessor { message: &Message, loaders: &mut [Vec<(Pubkey, Account)>], accounts: &mut [Account], - tick_height: u64, ) -> Result<(), TransactionError> { for (instruction_index, instruction) in message.instructions.iter().enumerate() { let executable_index = message @@ -239,7 +228,6 @@ impl MessageProcessor { instruction, executable_accounts, &mut program_accounts, - tick_height, ) .map_err(|err| TransactionError::InstructionError(instruction_index as u8, err))?; } diff --git a/runtime/src/native_loader.rs b/runtime/src/native_loader.rs index a400e64b13..9234968a86 100644 --- a/runtime/src/native_loader.rs +++ b/runtime/src/native_loader.rs @@ -59,7 +59,6 @@ pub fn entrypoint( program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], ix_data: &[u8], - tick_height: u64, symbol_cache: &SymbolCache, ) -> Result<(), InstructionError> { if keyed_accounts[0].account.executable { @@ -68,7 +67,7 @@ pub fn entrypoint( let name_vec = &names[0].account.data; if let Some(entrypoint) = symbol_cache.read().unwrap().get(name_vec) { unsafe { - return entrypoint(program_id, params, ix_data, tick_height); + return entrypoint(program_id, params, ix_data); } } let name = match str::from_utf8(name_vec) { @@ -95,7 +94,7 @@ pub fn entrypoint( return Err(InstructionError::GenericError); } }; - let ret = entrypoint(program_id, params, ix_data, tick_height); + let ret = entrypoint(program_id, params, ix_data); symbol_cache .write() .unwrap() diff --git a/runtime/src/system_instruction_processor.rs b/runtime/src/system_instruction_processor.rs index c0982f22d2..0bf58049df 100644 --- a/runtime/src/system_instruction_processor.rs +++ b/runtime/src/system_instruction_processor.rs @@ -70,7 +70,6 @@ pub fn process_instruction( _program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], data: &[u8], - _tick_height: u64, ) -> Result<(), InstructionError> { if let Ok(instruction) = bincode::deserialize(data) { trace!("process_instruction: {:?}", instruction); @@ -246,7 +245,7 @@ mod tests { program_id: another_program_owner, }; let data = serialize(&instruction).unwrap(); - let result = process_instruction(&system_program::id(), &mut keyed_accounts, &data, 0); + let result = process_instruction(&system_program::id(), &mut keyed_accounts, &data); assert_eq!(result, Err(InstructionError::IncorrectProgramId)); assert_eq!(from_account.owner, new_program_owner); } diff --git a/sdk/bpf/inc/solana_sdk.h b/sdk/bpf/inc/solana_sdk.h index 9fda355d9b..aeb6c8df81 100644 --- a/sdk/bpf/inc/solana_sdk.h +++ b/sdk/bpf/inc/solana_sdk.h @@ -199,7 +199,6 @@ typedef struct { uint64_t ka_num; /** Number of SolKeyedAccount entries in `ka` */ const uint8_t *data; /** pointer to the instruction data */ uint64_t data_len; /** Length in bytes of the instruction data */ - uint64_t tick_height; /** Current ledger tick */ const SolPubkey *program_id; /** program_id of the currently executing program */ } SolParameters; @@ -258,8 +257,6 @@ SOL_FN_PREFIX bool sol_deserialize( params->data = input; input += params->data_len; - params->tick_height = *(uint64_t *) input; - input += sizeof(uint64_t); params->program_id = (SolPubkey *) input; input += sizeof(SolPubkey); @@ -299,8 +296,6 @@ SOL_FN_PREFIX void sol_log_array(const uint8_t *array, int len) { * @param params Pointer to a SolParameters structure */ SOL_FN_PREFIX void sol_log_params(const SolParameters *params) { - sol_log("- Tick height:"); - sol_log_64(params->tick_height, 0, 0, 0, 0); sol_log("- Program identifier:"); sol_log_key(params->program_id); diff --git a/sdk/bpf/rust-utils/src/entrypoint.rs b/sdk/bpf/rust-utils/src/entrypoint.rs index 0b29b348cc..12e731efa4 100644 --- a/sdk/bpf/rust-utils/src/entrypoint.rs +++ b/sdk/bpf/rust-utils/src/entrypoint.rs @@ -32,8 +32,6 @@ pub struct SolKeyedAccount<'a> { /// Information about the state of the cluster immediately before the program /// started executing the current instruction pub struct SolClusterInfo<'a> { - /// Current ledger tick - pub tick_height: u64, ///program_id of the currently executing program pub program_id: SolPubkey<'a>, } @@ -142,12 +140,6 @@ pub unsafe fn deserialize<'a>( let data = { from_raw_parts(input.add(offset), data_length) }; offset += data_length; - // Tick height - - #[allow(clippy::cast_ptr_alignment)] - let tick_height = *(input.add(offset) as *const u64); - offset += size_of::(); - // Id let program_id = { @@ -157,7 +149,6 @@ pub unsafe fn deserialize<'a>( }; let info = SolClusterInfo { - tick_height, program_id, }; diff --git a/sdk/src/instruction_processor_utils.rs b/sdk/src/instruction_processor_utils.rs index 1545db9381..256040c6ea 100644 --- a/sdk/src/instruction_processor_utils.rs +++ b/sdk/src/instruction_processor_utils.rs @@ -11,7 +11,6 @@ pub type Entrypoint = unsafe extern "C" fn( program_id: &Pubkey, keyed_accounts: &mut [KeyedAccount], data: &[u8], - tick_height: u64, ) -> Result<(), InstructionError>; // Convenience macro to define the native program entrypoint. Supply a fn to this macro that @@ -24,9 +23,8 @@ macro_rules! solana_entrypoint( program_id: &solana_sdk::pubkey::Pubkey, keyed_accounts: &mut [solana_sdk::account::KeyedAccount], data: &[u8], - tick_height: u64 ) -> Result<(), solana_sdk::instruction::InstructionError> { - $entrypoint(program_id, keyed_accounts, data, tick_height) + $entrypoint(program_id, keyed_accounts, data) } ) ); diff --git a/sdk/src/syscall/mod.rs b/sdk/src/syscall/mod.rs index 7c9ba18001..eb2893facb 100644 --- a/sdk/src/syscall/mod.rs +++ b/sdk/src/syscall/mod.rs @@ -4,6 +4,7 @@ use crate::pubkey::Pubkey; pub mod fees; pub mod slot_hashes; +pub mod tick_height; /// "Sysca11111111111111111111111111111111111111" /// owner pubkey for syscall accounts diff --git a/sdk/src/syscall/tick_height.rs b/sdk/src/syscall/tick_height.rs new file mode 100644 index 0000000000..c38d6df012 --- /dev/null +++ b/sdk/src/syscall/tick_height.rs @@ -0,0 +1,64 @@ +//! This account contains the current cluster tick height +//! +use crate::account::Account; +use crate::account_utils::State; +use crate::pubkey::Pubkey; +use crate::syscall; +use bincode::serialized_size; + +/// "Sysca11TickHeight11111111111111111111111111" +/// tick_height account pubkey +const ID: [u8; 32] = [ + 6, 167, 211, 138, 69, 219, 242, 63, 162, 206, 168, 232, 212, 90, 152, 107, 220, 251, 113, 215, + 208, 229, 34, 163, 11, 168, 45, 109, 60, 0, 0, 0, +]; + +pub fn id() -> Pubkey { + Pubkey::new(&ID) +} + +pub fn check_id(pubkey: &Pubkey) -> bool { + pubkey.as_ref() == ID +} + +#[repr(C)] +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct TickHeight(u64); + +impl TickHeight { + pub fn from(account: &Account) -> Option { + account.state().ok().map(|res: Self| res.0) + } + pub fn to(tick_height: u64, account: &mut Account) -> Option<()> { + account.set_state(&TickHeight(tick_height)).ok() + } + + pub fn size_of() -> usize { + serialized_size(&TickHeight::default()).unwrap() as usize + } +} + +pub fn create_account(lamports: u64) -> Account { + Account::new(lamports, TickHeight::size_of(), &syscall::id()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tick_height_id() { + let name = "Sysca11TickHeight11111111111111111111111111"; + // To get the bytes above: + // dbg!((name, bs58::decode(name).into_vec().unwrap())); + assert_eq!(name, id().to_string()); + assert!(check_id(&id())); + } + + #[test] + fn test_tick_height_create_account() { + let account = create_account(1); + let tick_height = TickHeight::from(&account).unwrap(); + assert_eq!(tick_height, 0); + } +}