Add tick height syscall (#4497)
* Remove tick_height from entrypoint signature * Impl tick_height syscall and use in storage program * Properly remove tick height from bpf handling
This commit is contained in:
parent
ce04d2bfc2
commit
64e8a21d73
|
@ -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);
|
||||
|
||||
|
|
|
@ -233,7 +233,6 @@ fn serialize_parameters(
|
|||
program_id: &Pubkey,
|
||||
keyed_accounts: &mut [KeyedAccount],
|
||||
data: &[u8],
|
||||
tick_height: u64,
|
||||
) -> Vec<u8> {
|
||||
assert_eq!(32, mem::size_of::<Pubkey>());
|
||||
|
||||
|
@ -252,7 +251,6 @@ fn serialize_parameters(
|
|||
}
|
||||
v.write_u64::<LittleEndian>(data.len() as u64).unwrap();
|
||||
v.write_all(data).unwrap();
|
||||
v.write_u64::<LittleEndian>(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) => {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()");
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ fn entrypoint(
|
|||
_program_id: &Pubkey,
|
||||
_keyed_accounts: &mut [KeyedAccount],
|
||||
_data: &[u8],
|
||||
_tick_height: u64,
|
||||
) -> Result<(), InstructionError> {
|
||||
Err(InstructionError::GenericError)
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
);
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -8,7 +8,6 @@ pub fn process_instruction(
|
|||
program_id: &Pubkey,
|
||||
info: &mut [KeyedAccount],
|
||||
input: &[u8],
|
||||
_tick_height: u64,
|
||||
) -> Result<(), InstructionError> {
|
||||
solana_logger::setup();
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ fn process_instruction(
|
|||
_program_id: &Pubkey,
|
||||
_keyed_accounts: &mut [KeyedAccount],
|
||||
_data: &[u8],
|
||||
_tick_height: u64,
|
||||
) -> Result<(), InstructionError> {
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -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,19 +817,18 @@ 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<Result<()>> =
|
||||
loaded_accounts
|
||||
let executed: Vec<Result<()>> = 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),
|
||||
Ok((ref mut accounts, ref mut loaders)) => {
|
||||
self.message_processor
|
||||
.process_message(tx.message(), loaders, accounts)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -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<HashMap<Vec<u8>, Symbol<instruction_processor_utils::Entrypoint>>>;
|
||||
|
||||
|
@ -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))?;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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::<u64>();
|
||||
|
||||
// Id
|
||||
|
||||
let program_id = {
|
||||
|
@ -157,7 +149,6 @@ pub unsafe fn deserialize<'a>(
|
|||
};
|
||||
|
||||
let info = SolClusterInfo {
|
||||
tick_height,
|
||||
program_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<u64> {
|
||||
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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue