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:
Parth
2019-10-04 02:52:48 +05:30
committed by GitHub
parent cf2bcee607
commit 92ea11fca1
7 changed files with 168 additions and 16 deletions

View File

@ -20,6 +20,7 @@ use solana_sdk::account::KeyedAccount;
use solana_sdk::instruction::InstructionError;
use solana_sdk::loader_instruction::LoaderInstruction;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::sysvar::rent;
use std::convert::TryFrom;
use std::io::prelude::*;
use std::io::Error;
@ -109,10 +110,16 @@ pub fn process_instruction(
keyed_accounts[0].account.data[offset..offset + len].copy_from_slice(&bytes);
}
LoaderInstruction::Finalize => {
if keyed_accounts.len() < 2 {
return Err(InstructionError::InvalidInstructionData);
}
if keyed_accounts[0].signer_key().is_none() {
warn!("key[0] did not sign the transaction");
return Err(InstructionError::GenericError);
}
rent::verify_rent_exemption(&keyed_accounts[0], &keyed_accounts[1])?;
keyed_accounts[0].account.executable = true;
info!(
"Finalize: account {:?}",

View File

@ -7,7 +7,7 @@ use log::*;
use serde_derive::{Deserialize, Serialize};
use solana_sdk::{
account::KeyedAccount, instruction::InstructionError, loader_instruction::LoaderInstruction,
pubkey::Pubkey,
pubkey::Pubkey, sysvar::rent,
};
use types::{
account_address::AccountAddress,
@ -294,11 +294,16 @@ impl MoveProcessor {
}
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() {
debug!("Error: key[0] did not sign the transaction");
return Err(InstructionError::GenericError);
}
rent::verify_rent_exemption(&keyed_accounts[0], &keyed_accounts[1])?;
let (compiled_script, compiled_modules) =
Self::deserialize_compiled_program(&keyed_accounts[PROGRAM_INDEX].account.data)?;
@ -402,6 +407,8 @@ mod tests {
use super::*;
use language_e2e_tests::account::AccountResource;
use solana_sdk::account::Account;
use solana_sdk::rent_calculator::RentCalculator;
use solana_sdk::sysvar::rent;
#[test]
fn test_finalize() {
@ -410,7 +417,12 @@ mod tests {
let code = "main() { return; }";
let sender_address = AccountAddress::default();
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();
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 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![
KeyedAccount::new(&program.key, true, &mut program.account),
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
];
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
MoveProcessor::do_invoke_main(
&mut keyed_accounts,
&bincode::serialize(&InvokeCommand::RunProgram {
@ -482,11 +503,20 @@ mod tests {
let mut program = LibraAccount::create_program(&sender_address, code, vec![]);
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![
KeyedAccount::new(&program.key, true, &mut program.account),
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
];
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
assert_eq!(
MoveProcessor::do_invoke_main(
&mut keyed_accounts,
@ -547,13 +577,23 @@ mod tests {
let (genesis, sender) = accounts.split_at_mut(GENESIS_INDEX + 1);
let genesis = &mut genesis[1];
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![
KeyedAccount::new(&program.key, true, &mut program.account),
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
KeyedAccount::new(&sender.key, false, &mut sender.account),
KeyedAccount::new(&payee.key, false, &mut payee.account),
];
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
let amount = 2;
MoveProcessor::do_invoke_main(
&mut keyed_accounts,
@ -610,12 +650,21 @@ mod tests {
let mut payee = LibraAccount::create_unallocated();
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![
KeyedAccount::new(&program.key, true, &mut program.account),
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
KeyedAccount::new(&payee.key, false, &mut payee.account),
];
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
MoveProcessor::do_invoke_main(
&mut keyed_accounts,
&bincode::serialize(&InvokeCommand::RunProgram {
@ -645,12 +694,21 @@ mod tests {
let mut program = LibraAccount::create_program(&module.address, code, vec![]);
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![
KeyedAccount::new(&program.key, true, &mut program.account),
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
KeyedAccount::new(&module.key, false, &mut module.account),
];
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
MoveProcessor::do_invoke_main(
&mut keyed_accounts,
&bincode::serialize(&InvokeCommand::RunProgram {
@ -678,12 +736,21 @@ mod tests {
let mut program =
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![
KeyedAccount::new(&program.key, true, &mut program.account),
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
KeyedAccount::new(&module.key, false, &mut module.account),
];
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
MoveProcessor::do_invoke_main(
&mut keyed_accounts,
&bincode::serialize(&InvokeCommand::RunProgram {
@ -711,12 +778,21 @@ mod tests {
let mut program = LibraAccount::create_program(&genesis.address, code, vec![]);
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![
KeyedAccount::new(&program.key, true, &mut program.account),
KeyedAccount::new(&genesis.key, false, &mut genesis.account),
KeyedAccount::new(&payee.key, false, &mut payee.account),
];
MoveProcessor::do_finalize(&mut keyed_accounts).unwrap();
MoveProcessor::do_invoke_main(
&mut keyed_accounts,
&bincode::serialize(&InvokeCommand::RunProgram {

View File

@ -12,6 +12,7 @@ use solana_sdk::{
instruction_processor_utils::DecodeError,
pubkey::Pubkey,
system_instruction, sysvar,
sysvar::rent,
};
/// Reasons the stake might have had an error
@ -125,7 +126,10 @@ pub fn create_stake_account_with_lockup(
Instruction::new(
id(),
&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
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) => {
me.authorize(&authorized_pubkey, stake_authorize, &rest)
}
@ -349,7 +359,9 @@ pub fn process_instruction(
mod tests {
use super::*;
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> {
let mut accounts: Vec<_> = instruction
@ -364,6 +376,8 @@ mod tests {
sysvar::stake_history::create_account(1, &StakeHistory::default())
} else if config::check_id(&meta.pubkey) {
config::create_account(1, &config::Config::default())
} else if sysvar::rent::check_id(&meta.pubkey) {
sysvar::rent::create_account(1, &RentCalculator::default())
} else {
Account::default()
}

View File

@ -15,7 +15,8 @@ use solana_sdk::{
instruction::{AccountMeta, Instruction, InstructionError},
instruction_processor_utils::DecodeError,
pubkey::Pubkey,
system_instruction, sysvar,
system_instruction,
sysvar::{self, rent},
};
/// 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 {
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(
id(),
&VoteInstruction::InitializeAccount(*vote_init),
@ -176,6 +180,10 @@ pub fn process_instruction(
// TODO: data-driven unpack and dispatch of KeyedAccounts
match deserialize(data).map_err(|_| InstructionError::InvalidInstructionData)? {
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)
}
VoteInstruction::Authorize(voter_pubkey, vote_authorize) => {
@ -212,6 +220,7 @@ pub fn process_instruction(
mod tests {
use super::*;
use solana_sdk::account::Account;
use solana_sdk::rent_calculator::RentCalculator;
// these are for 100% coverage in this file
#[test]
@ -231,6 +240,8 @@ mod tests {
sysvar::clock::new_account(1, 0, 0, 0, 0)
} else if sysvar::slot_hashes::check_id(&meta.pubkey) {
sysvar::slot_hashes::create_account(1, &[])
} else if sysvar::rent::check_id(&meta.pubkey) {
sysvar::rent::create_account(1, &RentCalculator::default())
} else {
Account::default()
}