make executable, vote and stake account rent exempt (#6017)
* add missing convenience method * require vote account to be exempt * make stake account rent exempt * making executable rent exempt * rent will be initialized in genesis * add test for update_rent
This commit is contained in:
parent
cf2bcee607
commit
92ea11fca1
|
@ -20,6 +20,7 @@ use solana_sdk::account::KeyedAccount;
|
||||||
use solana_sdk::instruction::InstructionError;
|
use solana_sdk::instruction::InstructionError;
|
||||||
use solana_sdk::loader_instruction::LoaderInstruction;
|
use solana_sdk::loader_instruction::LoaderInstruction;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use solana_sdk::sysvar::rent;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
|
@ -109,10 +110,16 @@ pub fn process_instruction(
|
||||||
keyed_accounts[0].account.data[offset..offset + len].copy_from_slice(&bytes);
|
keyed_accounts[0].account.data[offset..offset + len].copy_from_slice(&bytes);
|
||||||
}
|
}
|
||||||
LoaderInstruction::Finalize => {
|
LoaderInstruction::Finalize => {
|
||||||
|
if keyed_accounts.len() < 2 {
|
||||||
|
return Err(InstructionError::InvalidInstructionData);
|
||||||
|
}
|
||||||
if keyed_accounts[0].signer_key().is_none() {
|
if keyed_accounts[0].signer_key().is_none() {
|
||||||
warn!("key[0] did not sign the transaction");
|
warn!("key[0] did not sign the transaction");
|
||||||
return Err(InstructionError::GenericError);
|
return Err(InstructionError::GenericError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rent::verify_rent_exemption(&keyed_accounts[0], &keyed_accounts[1])?;
|
||||||
|
|
||||||
keyed_accounts[0].account.executable = true;
|
keyed_accounts[0].account.executable = true;
|
||||||
info!(
|
info!(
|
||||||
"Finalize: account {:?}",
|
"Finalize: account {:?}",
|
||||||
|
|
|
@ -7,7 +7,7 @@ use log::*;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::KeyedAccount, instruction::InstructionError, loader_instruction::LoaderInstruction,
|
account::KeyedAccount, instruction::InstructionError, loader_instruction::LoaderInstruction,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey, sysvar::rent,
|
||||||
};
|
};
|
||||||
use types::{
|
use types::{
|
||||||
account_address::AccountAddress,
|
account_address::AccountAddress,
|
||||||
|
@ -294,11 +294,16 @@ impl MoveProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_finalize(keyed_accounts: &mut [KeyedAccount]) -> Result<(), InstructionError> {
|
pub fn do_finalize(keyed_accounts: &mut [KeyedAccount]) -> Result<(), InstructionError> {
|
||||||
|
if keyed_accounts.len() < 2 {
|
||||||
|
return Err(InstructionError::InvalidInstructionData);
|
||||||
|
}
|
||||||
if keyed_accounts[PROGRAM_INDEX].signer_key().is_none() {
|
if keyed_accounts[PROGRAM_INDEX].signer_key().is_none() {
|
||||||
debug!("Error: key[0] did not sign the transaction");
|
debug!("Error: key[0] did not sign the transaction");
|
||||||
return Err(InstructionError::GenericError);
|
return Err(InstructionError::GenericError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rent::verify_rent_exemption(&keyed_accounts[0], &keyed_accounts[1])?;
|
||||||
|
|
||||||
let (compiled_script, compiled_modules) =
|
let (compiled_script, compiled_modules) =
|
||||||
Self::deserialize_compiled_program(&keyed_accounts[PROGRAM_INDEX].account.data)?;
|
Self::deserialize_compiled_program(&keyed_accounts[PROGRAM_INDEX].account.data)?;
|
||||||
|
|
||||||
|
@ -402,6 +407,8 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use language_e2e_tests::account::AccountResource;
|
use language_e2e_tests::account::AccountResource;
|
||||||
use solana_sdk::account::Account;
|
use solana_sdk::account::Account;
|
||||||
|
use solana_sdk::rent_calculator::RentCalculator;
|
||||||
|
use solana_sdk::sysvar::rent;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_finalize() {
|
fn test_finalize() {
|
||||||
|
@ -410,7 +417,12 @@ mod tests {
|
||||||
let code = "main() { return; }";
|
let code = "main() { return; }";
|
||||||
let sender_address = AccountAddress::default();
|
let sender_address = AccountAddress::default();
|
||||||
let mut program = LibraAccount::create_program(&sender_address, code, vec![]);
|
let mut program = LibraAccount::create_program(&sender_address, code, vec![]);
|
||||||
let mut keyed_accounts = vec![KeyedAccount::new(&program.key, true, &mut program.account)];
|
let rent_id = rent::id();
|
||||||
|
let mut rent_account = rent::create_account(1, &RentCalculator::default());
|
||||||
|
let mut keyed_accounts = vec![
|
||||||
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
|
KeyedAccount::new(&rent_id, false, &mut rent_account),
|
||||||
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
let (_, _) = MoveProcessor::deserialize_verified_program(&program.account.data).unwrap();
|
let (_, _) = MoveProcessor::deserialize_verified_program(&program.account.data).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -451,11 +463,20 @@ mod tests {
|
||||||
let mut program = LibraAccount::create_program(&sender_address, code, vec![]);
|
let mut program = LibraAccount::create_program(&sender_address, code, vec![]);
|
||||||
let mut genesis = LibraAccount::create_genesis(1_000_000_000);
|
let mut genesis = LibraAccount::create_genesis(1_000_000_000);
|
||||||
|
|
||||||
|
let rent_id = rent::id();
|
||||||
|
let mut rent_account = rent::create_account(1, &RentCalculator::default());
|
||||||
|
let mut keyed_accounts = vec![
|
||||||
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
|
KeyedAccount::new(&rent_id, false, &mut rent_account),
|
||||||
|
];
|
||||||
|
|
||||||
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
|
|
||||||
let mut keyed_accounts = vec![
|
let mut keyed_accounts = vec![
|
||||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
&bincode::serialize(&InvokeCommand::RunProgram {
|
&bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
|
@ -482,11 +503,20 @@ mod tests {
|
||||||
let mut program = LibraAccount::create_program(&sender_address, code, vec![]);
|
let mut program = LibraAccount::create_program(&sender_address, code, vec![]);
|
||||||
let mut genesis = LibraAccount::create_genesis(1_000_000_000);
|
let mut genesis = LibraAccount::create_genesis(1_000_000_000);
|
||||||
|
|
||||||
|
let rent_id = rent::id();
|
||||||
|
let mut rent_account = rent::create_account(1, &RentCalculator::default());
|
||||||
|
let mut keyed_accounts = vec![
|
||||||
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
|
KeyedAccount::new(&rent_id, false, &mut rent_account),
|
||||||
|
];
|
||||||
|
|
||||||
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
|
|
||||||
let mut keyed_accounts = vec![
|
let mut keyed_accounts = vec![
|
||||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
|
@ -547,13 +577,23 @@ mod tests {
|
||||||
let (genesis, sender) = accounts.split_at_mut(GENESIS_INDEX + 1);
|
let (genesis, sender) = accounts.split_at_mut(GENESIS_INDEX + 1);
|
||||||
let genesis = &mut genesis[1];
|
let genesis = &mut genesis[1];
|
||||||
let sender = &mut sender[0];
|
let sender = &mut sender[0];
|
||||||
|
|
||||||
|
let rent_id = rent::id();
|
||||||
|
let mut rent_account = rent::create_account(1, &RentCalculator::default());
|
||||||
|
let mut keyed_accounts = vec![
|
||||||
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
|
KeyedAccount::new(&rent_id, false, &mut rent_account),
|
||||||
|
];
|
||||||
|
|
||||||
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
|
|
||||||
let mut keyed_accounts = vec![
|
let mut keyed_accounts = vec![
|
||||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||||
KeyedAccount::new(&sender.key, false, &mut sender.account),
|
KeyedAccount::new(&sender.key, false, &mut sender.account),
|
||||||
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
|
||||||
let amount = 2;
|
let amount = 2;
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
|
@ -610,12 +650,21 @@ mod tests {
|
||||||
let mut payee = LibraAccount::create_unallocated();
|
let mut payee = LibraAccount::create_unallocated();
|
||||||
let mut program = LibraAccount::create_program(&payee.address, code, vec![]);
|
let mut program = LibraAccount::create_program(&payee.address, code, vec![]);
|
||||||
|
|
||||||
|
let rent_id = rent::id();
|
||||||
|
let mut rent_account = rent::create_account(1, &RentCalculator::default());
|
||||||
|
let mut keyed_accounts = vec![
|
||||||
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
|
KeyedAccount::new(&rent_id, false, &mut rent_account),
|
||||||
|
];
|
||||||
|
|
||||||
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
|
|
||||||
let mut keyed_accounts = vec![
|
let mut keyed_accounts = vec![
|
||||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||||
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
&bincode::serialize(&InvokeCommand::RunProgram {
|
&bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
|
@ -645,12 +694,21 @@ mod tests {
|
||||||
let mut program = LibraAccount::create_program(&module.address, code, vec![]);
|
let mut program = LibraAccount::create_program(&module.address, code, vec![]);
|
||||||
let mut genesis = LibraAccount::create_genesis(1_000_000_000);
|
let mut genesis = LibraAccount::create_genesis(1_000_000_000);
|
||||||
|
|
||||||
|
let rent_id = rent::id();
|
||||||
|
let mut rent_account = rent::create_account(1, &RentCalculator::default());
|
||||||
|
let mut keyed_accounts = vec![
|
||||||
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
|
KeyedAccount::new(&rent_id, false, &mut rent_account),
|
||||||
|
];
|
||||||
|
|
||||||
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
|
|
||||||
let mut keyed_accounts = vec![
|
let mut keyed_accounts = vec![
|
||||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||||
KeyedAccount::new(&module.key, false, &mut module.account),
|
KeyedAccount::new(&module.key, false, &mut module.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
&bincode::serialize(&InvokeCommand::RunProgram {
|
&bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
|
@ -678,12 +736,21 @@ mod tests {
|
||||||
let mut program =
|
let mut program =
|
||||||
LibraAccount::create_program(&module.address, &code, vec![&module.account.data]);
|
LibraAccount::create_program(&module.address, &code, vec![&module.account.data]);
|
||||||
|
|
||||||
|
let rent_id = rent::id();
|
||||||
|
let mut rent_account = rent::create_account(1, &RentCalculator::default());
|
||||||
|
let mut keyed_accounts = vec![
|
||||||
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
|
KeyedAccount::new(&rent_id, false, &mut rent_account),
|
||||||
|
];
|
||||||
|
|
||||||
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
|
|
||||||
let mut keyed_accounts = vec![
|
let mut keyed_accounts = vec![
|
||||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||||
KeyedAccount::new(&module.key, false, &mut module.account),
|
KeyedAccount::new(&module.key, false, &mut module.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
&bincode::serialize(&InvokeCommand::RunProgram {
|
&bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
|
@ -711,12 +778,21 @@ mod tests {
|
||||||
let mut program = LibraAccount::create_program(&genesis.address, code, vec![]);
|
let mut program = LibraAccount::create_program(&genesis.address, code, vec![]);
|
||||||
let mut payee = LibraAccount::create_unallocated();
|
let mut payee = LibraAccount::create_unallocated();
|
||||||
|
|
||||||
|
let rent_id = rent::id();
|
||||||
|
let mut rent_account = rent::create_account(1, &RentCalculator::default());
|
||||||
|
let mut keyed_accounts = vec![
|
||||||
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
|
KeyedAccount::new(&rent_id, false, &mut rent_account),
|
||||||
|
];
|
||||||
|
|
||||||
|
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
||||||
|
|
||||||
let mut keyed_accounts = vec![
|
let mut keyed_accounts = vec![
|
||||||
KeyedAccount::new(&program.key, true, &mut program.account),
|
KeyedAccount::new(&program.key, true, &mut program.account),
|
||||||
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
|
||||||
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
KeyedAccount::new(&payee.key, false, &mut payee.account),
|
||||||
];
|
];
|
||||||
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
|
|
||||||
MoveProcessor::do_invoke_main(
|
MoveProcessor::do_invoke_main(
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
&bincode::serialize(&InvokeCommand::RunProgram {
|
&bincode::serialize(&InvokeCommand::RunProgram {
|
||||||
|
|
|
@ -12,6 +12,7 @@ use solana_sdk::{
|
||||||
instruction_processor_utils::DecodeError,
|
instruction_processor_utils::DecodeError,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
system_instruction, sysvar,
|
system_instruction, sysvar,
|
||||||
|
sysvar::rent,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Reasons the stake might have had an error
|
/// Reasons the stake might have had an error
|
||||||
|
@ -125,7 +126,10 @@ pub fn create_stake_account_with_lockup(
|
||||||
Instruction::new(
|
Instruction::new(
|
||||||
id(),
|
id(),
|
||||||
&StakeInstruction::Initialize(*authorized, *lockup),
|
&StakeInstruction::Initialize(*authorized, *lockup),
|
||||||
vec![AccountMeta::new(*stake_pubkey, false)],
|
vec![
|
||||||
|
AccountMeta::new(*stake_pubkey, false),
|
||||||
|
AccountMeta::new(sysvar::rent::id(), false),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -281,7 +285,13 @@ pub fn process_instruction(
|
||||||
|
|
||||||
// TODO: data-driven unpack and dispatch of KeyedAccounts
|
// TODO: data-driven unpack and dispatch of KeyedAccounts
|
||||||
match deserialize(data).map_err(|_| InstructionError::InvalidInstructionData)? {
|
match deserialize(data).map_err(|_| InstructionError::InvalidInstructionData)? {
|
||||||
StakeInstruction::Initialize(authorized, lockup) => me.initialize(&authorized, &lockup),
|
StakeInstruction::Initialize(authorized, lockup) => {
|
||||||
|
if rest.is_empty() {
|
||||||
|
Err(InstructionError::InvalidInstructionData)?;
|
||||||
|
}
|
||||||
|
rent::verify_rent_exemption(me, &rest[0])?;
|
||||||
|
me.initialize(&authorized, &lockup)
|
||||||
|
}
|
||||||
StakeInstruction::Authorize(authorized_pubkey, stake_authorize) => {
|
StakeInstruction::Authorize(authorized_pubkey, stake_authorize) => {
|
||||||
me.authorize(&authorized_pubkey, stake_authorize, &rest)
|
me.authorize(&authorized_pubkey, stake_authorize, &rest)
|
||||||
}
|
}
|
||||||
|
@ -349,7 +359,9 @@ pub fn process_instruction(
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use solana_sdk::{account::Account, sysvar::stake_history::StakeHistory};
|
use solana_sdk::{
|
||||||
|
account::Account, rent_calculator::RentCalculator, sysvar::stake_history::StakeHistory,
|
||||||
|
};
|
||||||
|
|
||||||
fn process_instruction(instruction: &Instruction) -> Result<(), InstructionError> {
|
fn process_instruction(instruction: &Instruction) -> Result<(), InstructionError> {
|
||||||
let mut accounts: Vec<_> = instruction
|
let mut accounts: Vec<_> = instruction
|
||||||
|
@ -364,6 +376,8 @@ mod tests {
|
||||||
sysvar::stake_history::create_account(1, &StakeHistory::default())
|
sysvar::stake_history::create_account(1, &StakeHistory::default())
|
||||||
} else if config::check_id(&meta.pubkey) {
|
} else if config::check_id(&meta.pubkey) {
|
||||||
config::create_account(1, &config::Config::default())
|
config::create_account(1, &config::Config::default())
|
||||||
|
} else if sysvar::rent::check_id(&meta.pubkey) {
|
||||||
|
sysvar::rent::create_account(1, &RentCalculator::default())
|
||||||
} else {
|
} else {
|
||||||
Account::default()
|
Account::default()
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ use solana_sdk::{
|
||||||
instruction::{AccountMeta, Instruction, InstructionError},
|
instruction::{AccountMeta, Instruction, InstructionError},
|
||||||
instruction_processor_utils::DecodeError,
|
instruction_processor_utils::DecodeError,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
system_instruction, sysvar,
|
system_instruction,
|
||||||
|
sysvar::{self, rent},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Reasons the stake might have had an error
|
/// Reasons the stake might have had an error
|
||||||
|
@ -65,7 +66,10 @@ pub enum VoteInstruction {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_account(vote_pubkey: &Pubkey, vote_init: &VoteInit) -> Instruction {
|
fn initialize_account(vote_pubkey: &Pubkey, vote_init: &VoteInit) -> Instruction {
|
||||||
let account_metas = vec![AccountMeta::new(*vote_pubkey, false)];
|
let account_metas = vec![
|
||||||
|
AccountMeta::new(*vote_pubkey, false),
|
||||||
|
AccountMeta::new(sysvar::rent::id(), false),
|
||||||
|
];
|
||||||
Instruction::new(
|
Instruction::new(
|
||||||
id(),
|
id(),
|
||||||
&VoteInstruction::InitializeAccount(*vote_init),
|
&VoteInstruction::InitializeAccount(*vote_init),
|
||||||
|
@ -176,6 +180,10 @@ pub fn process_instruction(
|
||||||
// TODO: data-driven unpack and dispatch of KeyedAccounts
|
// TODO: data-driven unpack and dispatch of KeyedAccounts
|
||||||
match deserialize(data).map_err(|_| InstructionError::InvalidInstructionData)? {
|
match deserialize(data).map_err(|_| InstructionError::InvalidInstructionData)? {
|
||||||
VoteInstruction::InitializeAccount(vote_init) => {
|
VoteInstruction::InitializeAccount(vote_init) => {
|
||||||
|
if rest.is_empty() {
|
||||||
|
Err(InstructionError::InvalidInstructionData)?;
|
||||||
|
}
|
||||||
|
rent::verify_rent_exemption(me, &rest[0])?;
|
||||||
vote_state::initialize_account(me, &vote_init)
|
vote_state::initialize_account(me, &vote_init)
|
||||||
}
|
}
|
||||||
VoteInstruction::Authorize(voter_pubkey, vote_authorize) => {
|
VoteInstruction::Authorize(voter_pubkey, vote_authorize) => {
|
||||||
|
@ -212,6 +220,7 @@ pub fn process_instruction(
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use solana_sdk::account::Account;
|
use solana_sdk::account::Account;
|
||||||
|
use solana_sdk::rent_calculator::RentCalculator;
|
||||||
|
|
||||||
// these are for 100% coverage in this file
|
// these are for 100% coverage in this file
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -231,6 +240,8 @@ mod tests {
|
||||||
sysvar::clock::new_account(1, 0, 0, 0, 0)
|
sysvar::clock::new_account(1, 0, 0, 0, 0)
|
||||||
} else if sysvar::slot_hashes::check_id(&meta.pubkey) {
|
} else if sysvar::slot_hashes::check_id(&meta.pubkey) {
|
||||||
sysvar::slot_hashes::create_account(1, &[])
|
sysvar::slot_hashes::create_account(1, &[])
|
||||||
|
} else if sysvar::rent::check_id(&meta.pubkey) {
|
||||||
|
sysvar::rent::create_account(1, &RentCalculator::default())
|
||||||
} else {
|
} else {
|
||||||
Account::default()
|
Account::default()
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,6 +283,7 @@ impl Bank {
|
||||||
bank.update_stake_history(None);
|
bank.update_stake_history(None);
|
||||||
}
|
}
|
||||||
bank.update_clock();
|
bank.update_clock();
|
||||||
|
bank.update_rent();
|
||||||
bank
|
bank
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1594,6 +1595,7 @@ mod tests {
|
||||||
use solana_sdk::hash;
|
use solana_sdk::hash;
|
||||||
use solana_sdk::instruction::InstructionError;
|
use solana_sdk::instruction::InstructionError;
|
||||||
use solana_sdk::poh_config::PohConfig;
|
use solana_sdk::poh_config::PohConfig;
|
||||||
|
use solana_sdk::rent_calculator::RentCalculator;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::system_instruction;
|
use solana_sdk::system_instruction;
|
||||||
use solana_sdk::system_transaction;
|
use solana_sdk::system_transaction;
|
||||||
|
@ -1611,7 +1613,7 @@ mod tests {
|
||||||
let dummy_leader_lamports = BOOTSTRAP_LEADER_LAMPORTS;
|
let dummy_leader_lamports = BOOTSTRAP_LEADER_LAMPORTS;
|
||||||
let mint_lamports = 10_000;
|
let mint_lamports = 10_000;
|
||||||
let GenesisBlockInfo {
|
let GenesisBlockInfo {
|
||||||
genesis_block,
|
mut genesis_block,
|
||||||
mint_keypair,
|
mint_keypair,
|
||||||
voting_keypair,
|
voting_keypair,
|
||||||
..
|
..
|
||||||
|
@ -1620,12 +1622,25 @@ mod tests {
|
||||||
&dummy_leader_pubkey,
|
&dummy_leader_pubkey,
|
||||||
dummy_leader_lamports,
|
dummy_leader_lamports,
|
||||||
);
|
);
|
||||||
|
genesis_block.rent_calculator = RentCalculator {
|
||||||
|
lamports_per_byte_year: 5,
|
||||||
|
exemption_threshold: 1.2,
|
||||||
|
burn_percent: 5,
|
||||||
|
};
|
||||||
|
|
||||||
let bank = Bank::new(&genesis_block);
|
let bank = Bank::new(&genesis_block);
|
||||||
assert_eq!(bank.get_balance(&mint_keypair.pubkey()), mint_lamports);
|
assert_eq!(bank.get_balance(&mint_keypair.pubkey()), mint_lamports);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
bank.get_balance(&voting_keypair.pubkey()),
|
bank.get_balance(&voting_keypair.pubkey()),
|
||||||
dummy_leader_lamports /* 1 token goes to the vote account associated with dummy_leader_lamports */
|
dummy_leader_lamports /* 1 token goes to the vote account associated with dummy_leader_lamports */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let rent_account = bank.get_account(&rent::id()).unwrap();
|
||||||
|
let rent_sysvar = rent::Rent::from_account(&rent_account).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(rent_sysvar.rent_calculator.burn_percent, 5);
|
||||||
|
assert_eq!(rent_sysvar.rent_calculator.exemption_threshold, 1.2);
|
||||||
|
assert_eq!(rent_sysvar.rent_calculator.lamports_per_byte_year, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::instruction::{AccountMeta, Instruction};
|
use crate::instruction::{AccountMeta, Instruction};
|
||||||
use crate::pubkey::Pubkey;
|
use crate::pubkey::Pubkey;
|
||||||
|
use crate::sysvar::rent;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum LoaderInstruction {
|
pub enum LoaderInstruction {
|
||||||
|
@ -15,6 +16,7 @@ pub enum LoaderInstruction {
|
||||||
/// bit of the Account
|
/// bit of the Account
|
||||||
///
|
///
|
||||||
/// * key[0] - the account to prepare for execution
|
/// * key[0] - the account to prepare for execution
|
||||||
|
/// * key[1] - rent sysvar account
|
||||||
///
|
///
|
||||||
/// The transaction must be signed by key[0]
|
/// The transaction must be signed by key[0]
|
||||||
Finalize,
|
Finalize,
|
||||||
|
@ -40,6 +42,9 @@ pub fn write(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finalize(account_pubkey: &Pubkey, program_id: &Pubkey) -> Instruction {
|
pub fn finalize(account_pubkey: &Pubkey, program_id: &Pubkey) -> Instruction {
|
||||||
let account_metas = vec![AccountMeta::new(*account_pubkey, true)];
|
let account_metas = vec![
|
||||||
|
AccountMeta::new(*account_pubkey, true),
|
||||||
|
AccountMeta::new(rent::id(), false),
|
||||||
|
];
|
||||||
Instruction::new(*program_id, &LoaderInstruction::Finalize, account_metas)
|
Instruction::new(*program_id, &LoaderInstruction::Finalize, account_metas)
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,30 @@ pub fn create_account(lamports: u64, rent_calculator: &RentCalculator) -> Accoun
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::account::KeyedAccount;
|
||||||
|
use crate::instruction::InstructionError;
|
||||||
|
|
||||||
|
pub fn from_keyed_account(account: &KeyedAccount) -> Result<Rent, InstructionError> {
|
||||||
|
if !check_id(account.unsigned_key()) {
|
||||||
|
return Err(InstructionError::InvalidArgument);
|
||||||
|
}
|
||||||
|
Rent::from_account(account.account).ok_or(InstructionError::InvalidArgument)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify_rent_exemption(
|
||||||
|
account: &KeyedAccount,
|
||||||
|
rent_sysvar_account: &KeyedAccount,
|
||||||
|
) -> Result<(), InstructionError> {
|
||||||
|
if !from_keyed_account(rent_sysvar_account)?
|
||||||
|
.rent_calculator
|
||||||
|
.is_exempt(account.account.lamports, account.account.data.len())
|
||||||
|
{
|
||||||
|
Err(InstructionError::InsufficientFunds)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in New Issue