Don't use global storage account
Other accounts would not be able to modify the system accounts userdata.
This commit is contained in:
committed by
sakridge
parent
6bca577d6d
commit
66891d9d4e
@ -33,7 +33,7 @@ fn entrypoint(
|
|||||||
) -> Result<(), ProgramError> {
|
) -> Result<(), ProgramError> {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
|
||||||
if keyed_accounts.len() != 2 {
|
if keyed_accounts.len() != 1 {
|
||||||
// keyed_accounts[1] should be the main storage key
|
// keyed_accounts[1] should be the main storage key
|
||||||
// to access its userdata
|
// to access its userdata
|
||||||
Err(ProgramError::InvalidArgument)?;
|
Err(ProgramError::InvalidArgument)?;
|
||||||
@ -45,26 +45,9 @@ fn entrypoint(
|
|||||||
Err(ProgramError::GenericError)?;
|
Err(ProgramError::GenericError)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Following https://github.com/solana-labs/solana/pull/2773,
|
|
||||||
// Modifications to userdata can only be made by accounts owned
|
|
||||||
// by this program. TODO: Add this check:
|
|
||||||
//if !check_id(&keyed_accounts[1].account.owner) {
|
|
||||||
// error!("account[1] is not assigned to the STORAGE_PROGRAM");
|
|
||||||
// Err(ProgramError::InvalidArgument)?;
|
|
||||||
//}
|
|
||||||
|
|
||||||
if *keyed_accounts[1].unsigned_key() != system_id() {
|
|
||||||
info!(
|
|
||||||
"invalid account id owner: {:?} system_id: {:?}",
|
|
||||||
keyed_accounts[1].unsigned_key(),
|
|
||||||
system_id()
|
|
||||||
);
|
|
||||||
Err(ProgramError::InvalidArgument)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Ok(syscall) = bincode::deserialize(data) {
|
if let Ok(syscall) = bincode::deserialize(data) {
|
||||||
let mut storage_account_state = if let Ok(storage_account_state) =
|
let mut storage_account_state = if let Ok(storage_account_state) =
|
||||||
bincode::deserialize(&keyed_accounts[1].account.userdata)
|
bincode::deserialize(&keyed_accounts[0].account.userdata)
|
||||||
{
|
{
|
||||||
storage_account_state
|
storage_account_state
|
||||||
} else {
|
} else {
|
||||||
@ -176,7 +159,7 @@ fn entrypoint(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if bincode::serialize_into(
|
if bincode::serialize_into(
|
||||||
&mut keyed_accounts[1].account.userdata[..],
|
&mut keyed_accounts[0].account.userdata[..],
|
||||||
&storage_account_state,
|
&storage_account_state,
|
||||||
)
|
)
|
||||||
.is_err()
|
.is_err()
|
||||||
@ -197,7 +180,6 @@ mod test {
|
|||||||
use solana_sdk::account::{create_keyed_accounts, Account};
|
use solana_sdk::account::{create_keyed_accounts, Account};
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
use solana_sdk::storage_program;
|
|
||||||
use solana_sdk::storage_program::ProofStatus;
|
use solana_sdk::storage_program::ProofStatus;
|
||||||
use solana_sdk::storage_program::StorageTransaction;
|
use solana_sdk::storage_program::StorageTransaction;
|
||||||
use solana_sdk::transaction::{Instruction, Transaction};
|
use solana_sdk::transaction::{Instruction, Transaction};
|
||||||
@ -244,11 +226,8 @@ mod test {
|
|||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let mut keyed_accounts = Vec::new();
|
let mut keyed_accounts = Vec::new();
|
||||||
let mut user_account = Account::default();
|
let mut user_account = Account::default();
|
||||||
let mut system_account = Account::default();
|
|
||||||
let pubkey = keypair.pubkey();
|
let pubkey = keypair.pubkey();
|
||||||
let system_key = storage_program::system_id();
|
|
||||||
keyed_accounts.push(KeyedAccount::new(&pubkey, true, &mut user_account));
|
keyed_accounts.push(KeyedAccount::new(&pubkey, true, &mut user_account));
|
||||||
keyed_accounts.push(KeyedAccount::new(&system_key, false, &mut system_account));
|
|
||||||
|
|
||||||
let tx = StorageTransaction::new_advertise_last_id(
|
let tx = StorageTransaction::new_advertise_last_id(
|
||||||
&keypair,
|
&keypair,
|
||||||
@ -306,7 +285,7 @@ mod test {
|
|||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let mut accounts = [Account::default(), Account::default()];
|
let mut accounts = [Account::default(), Account::default()];
|
||||||
accounts[1].userdata.resize(16 * 1024, 0);
|
accounts[0].userdata.resize(16 * 1024, 0);
|
||||||
|
|
||||||
let tx = StorageTransaction::new_advertise_last_id(
|
let tx = StorageTransaction::new_advertise_last_id(
|
||||||
&keypair,
|
&keypair,
|
||||||
@ -333,7 +312,7 @@ mod test {
|
|||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let mut accounts = [Account::default(), Account::default()];
|
let mut accounts = [Account::default(), Account::default()];
|
||||||
accounts[1].userdata.resize(16 * 1024, 0);
|
accounts[0].userdata.resize(16 * 1024, 0);
|
||||||
|
|
||||||
let entry_height = 0;
|
let entry_height = 0;
|
||||||
|
|
||||||
|
@ -3,12 +3,14 @@ use log::info;
|
|||||||
use solana_runtime::bank::Bank;
|
use solana_runtime::bank::Bank;
|
||||||
use solana_sdk::genesis_block::GenesisBlock;
|
use solana_sdk::genesis_block::GenesisBlock;
|
||||||
use solana_sdk::hash::{hash, Hash};
|
use solana_sdk::hash::{hash, Hash};
|
||||||
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
use solana_sdk::storage_program;
|
use solana_sdk::storage_program;
|
||||||
use solana_sdk::storage_program::{StorageTransaction, ENTRIES_PER_SEGMENT};
|
use solana_sdk::storage_program::{StorageTransaction, ENTRIES_PER_SEGMENT};
|
||||||
|
use solana_sdk::system_transaction::SystemTransaction;
|
||||||
|
|
||||||
fn get_storage_entry_height(bank: &Bank) -> u64 {
|
fn get_storage_entry_height(bank: &Bank, account: Pubkey) -> u64 {
|
||||||
match bank.get_account(&storage_program::system_id()) {
|
match bank.get_account(&account) {
|
||||||
Some(storage_system_account) => {
|
Some(storage_system_account) => {
|
||||||
let state = deserialize(&storage_system_account.userdata);
|
let state = deserialize(&storage_system_account.userdata);
|
||||||
if let Ok(state) = state {
|
if let Ok(state) = state {
|
||||||
@ -23,8 +25,8 @@ fn get_storage_entry_height(bank: &Bank) -> u64 {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_storage_last_id(bank: &Bank) -> Hash {
|
fn get_storage_last_id(bank: &Bank, account: Pubkey) -> Hash {
|
||||||
if let Some(storage_system_account) = bank.get_account(&storage_program::system_id()) {
|
if let Some(storage_system_account) = bank.get_account(&account) {
|
||||||
let state = deserialize(&storage_system_account.userdata);
|
let state = deserialize(&storage_system_account.userdata);
|
||||||
if let Ok(state) = state {
|
if let Ok(state) = state {
|
||||||
let state: storage_program::StorageProgramState = state;
|
let state: storage_program::StorageProgramState = state;
|
||||||
@ -35,7 +37,6 @@ fn get_storage_last_id(bank: &Bank) -> Hash {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn test_bank_storage() {
|
fn test_bank_storage() {
|
||||||
let (genesis_block, alice) = GenesisBlock::new(1000);
|
let (genesis_block, alice) = GenesisBlock::new(1000);
|
||||||
let bank = Bank::new(&genesis_block);
|
let bank = Bank::new(&genesis_block);
|
||||||
@ -56,6 +57,18 @@ fn test_bank_storage() {
|
|||||||
bank.transfer(10, &alice, bob.pubkey(), last_id).unwrap();
|
bank.transfer(10, &alice, bob.pubkey(), last_id).unwrap();
|
||||||
bank.transfer(10, &alice, jack.pubkey(), last_id).unwrap();
|
bank.transfer(10, &alice, jack.pubkey(), last_id).unwrap();
|
||||||
|
|
||||||
|
let tx = SystemTransaction::new_program_account(
|
||||||
|
&alice,
|
||||||
|
bob.pubkey(),
|
||||||
|
last_id,
|
||||||
|
1,
|
||||||
|
4 * 1024,
|
||||||
|
storage_program::id(),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
bank.process_transaction(&tx).unwrap();
|
||||||
|
|
||||||
let tx = StorageTransaction::new_advertise_last_id(
|
let tx = StorageTransaction::new_advertise_last_id(
|
||||||
&bob,
|
&bob,
|
||||||
storage_last_id,
|
storage_last_id,
|
||||||
@ -77,6 +90,9 @@ fn test_bank_storage() {
|
|||||||
|
|
||||||
bank.process_transaction(&tx).unwrap();
|
bank.process_transaction(&tx).unwrap();
|
||||||
|
|
||||||
assert_eq!(get_storage_entry_height(&bank), ENTRIES_PER_SEGMENT);
|
assert_eq!(
|
||||||
assert_eq!(get_storage_last_id(&bank), storage_last_id);
|
get_storage_entry_height(&bank, bob.pubkey()),
|
||||||
|
ENTRIES_PER_SEGMENT
|
||||||
|
);
|
||||||
|
assert_eq!(get_storage_last_id(&bank, bob.pubkey()), storage_last_id);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use crate::accounts::{Accounts, ErrorCounters, InstructionAccounts, InstructionL
|
|||||||
use crate::last_id_queue::LastIdQueue;
|
use crate::last_id_queue::LastIdQueue;
|
||||||
use crate::runtime::{self, RuntimeError};
|
use crate::runtime::{self, RuntimeError};
|
||||||
use crate::status_cache::StatusCache;
|
use crate::status_cache::StatusCache;
|
||||||
use bincode::{deserialize, serialize};
|
use bincode::serialize;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use log::{debug, info, Level};
|
use log::{debug, info, Level};
|
||||||
use solana_metrics::counter::Counter;
|
use solana_metrics::counter::Counter;
|
||||||
@ -219,13 +219,6 @@ impl Bank {
|
|||||||
self.add_native_program("solana_bpf_loader", &bpf_loader::id());
|
self.add_native_program("solana_bpf_loader", &bpf_loader::id());
|
||||||
self.add_native_program("solana_budget_program", &budget_program::id());
|
self.add_native_program("solana_budget_program", &budget_program::id());
|
||||||
self.add_native_program("solana_erc20", &token_program::id());
|
self.add_native_program("solana_erc20", &token_program::id());
|
||||||
|
|
||||||
let storage_system_account = Account::new(1, 16 * 1024, storage_program::system_id());
|
|
||||||
self.accounts.store_slow(
|
|
||||||
self.is_root(),
|
|
||||||
&storage_program::system_id(),
|
|
||||||
&storage_system_account,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the last entry ID registered.
|
/// Return the last entry ID registered.
|
||||||
@ -237,33 +230,6 @@ impl Bank {
|
|||||||
.expect("no last_id has been set")
|
.expect("no last_id has been set")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_storage_entry_height(&self) -> u64 {
|
|
||||||
match self.get_account(&storage_program::system_id()) {
|
|
||||||
Some(storage_system_account) => {
|
|
||||||
let state = deserialize(&storage_system_account.userdata);
|
|
||||||
if let Ok(state) = state {
|
|
||||||
let state: storage_program::StorageProgramState = state;
|
|
||||||
return state.entry_height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
info!("error in reading entry_height");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_storage_last_id(&self) -> Hash {
|
|
||||||
if let Some(storage_system_account) = self.get_account(&storage_program::system_id()) {
|
|
||||||
let state = deserialize(&storage_system_account.userdata);
|
|
||||||
if let Ok(state) = state {
|
|
||||||
let state: storage_program::StorageProgramState = state;
|
|
||||||
return state.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Hash::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Forget all signatures. Useful for benchmarking.
|
/// Forget all signatures. Useful for benchmarking.
|
||||||
pub fn clear_signatures(&self) {
|
pub fn clear_signatures(&self) {
|
||||||
self.status_cache.write().unwrap().clear();
|
self.status_cache.write().unwrap().clear();
|
||||||
@ -1232,10 +1198,6 @@ mod tests {
|
|||||||
132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
]);
|
]);
|
||||||
let storage_system = Pubkey::new(&[
|
|
||||||
133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0,
|
|
||||||
]);
|
|
||||||
|
|
||||||
assert_eq!(system_program::id(), system);
|
assert_eq!(system_program::id(), system);
|
||||||
assert_eq!(native_loader::id(), native);
|
assert_eq!(native_loader::id(), native);
|
||||||
@ -1244,7 +1206,6 @@ mod tests {
|
|||||||
assert_eq!(storage_program::id(), storage);
|
assert_eq!(storage_program::id(), storage);
|
||||||
assert_eq!(token_program::id(), token);
|
assert_eq!(token_program::id(), token);
|
||||||
assert_eq!(vote_program::id(), vote);
|
assert_eq!(vote_program::id(), vote);
|
||||||
assert_eq!(storage_program::system_id(), storage_system);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1258,7 +1219,6 @@ mod tests {
|
|||||||
storage_program::id(),
|
storage_program::id(),
|
||||||
token_program::id(),
|
token_program::id(),
|
||||||
vote_program::id(),
|
vote_program::id(),
|
||||||
storage_program::system_id(),
|
|
||||||
];
|
];
|
||||||
assert!(ids.into_iter().all(move |id| unique.insert(id)));
|
assert!(ids.into_iter().all(move |id| unique.insert(id)));
|
||||||
}
|
}
|
||||||
|
@ -66,11 +66,6 @@ pub const STORAGE_PROGRAM_ID: [u8; 32] = [
|
|||||||
0,
|
0,
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const STORAGE_SYSTEM_ACCOUNT_ID: [u8; 32] = [
|
|
||||||
133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0,
|
|
||||||
];
|
|
||||||
|
|
||||||
pub fn check_id(program_id: &Pubkey) -> bool {
|
pub fn check_id(program_id: &Pubkey) -> bool {
|
||||||
program_id.as_ref() == STORAGE_PROGRAM_ID
|
program_id.as_ref() == STORAGE_PROGRAM_ID
|
||||||
}
|
}
|
||||||
@ -79,10 +74,6 @@ pub fn id() -> Pubkey {
|
|||||||
Pubkey::new(&STORAGE_PROGRAM_ID)
|
Pubkey::new(&STORAGE_PROGRAM_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn system_id() -> Pubkey {
|
|
||||||
Pubkey::new(&STORAGE_SYSTEM_ACCOUNT_ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct StorageTransaction {}
|
pub struct StorageTransaction {}
|
||||||
|
|
||||||
impl StorageTransaction {
|
impl StorageTransaction {
|
||||||
@ -98,14 +89,7 @@ impl StorageTransaction {
|
|||||||
entry_height,
|
entry_height,
|
||||||
signature,
|
signature,
|
||||||
};
|
};
|
||||||
Transaction::new(
|
Transaction::new(from_keypair, &[], id(), &program, last_id, 0)
|
||||||
from_keypair,
|
|
||||||
&[Pubkey::new(&STORAGE_SYSTEM_ACCOUNT_ID)],
|
|
||||||
id(),
|
|
||||||
&program,
|
|
||||||
last_id,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_advertise_last_id(
|
pub fn new_advertise_last_id(
|
||||||
@ -118,14 +102,7 @@ impl StorageTransaction {
|
|||||||
id: storage_id,
|
id: storage_id,
|
||||||
entry_height,
|
entry_height,
|
||||||
};
|
};
|
||||||
Transaction::new(
|
Transaction::new(from_keypair, &[], id(), &program, last_id, 0)
|
||||||
from_keypair,
|
|
||||||
&[Pubkey::new(&STORAGE_SYSTEM_ACCOUNT_ID)],
|
|
||||||
id(),
|
|
||||||
&program,
|
|
||||||
last_id,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_proof_validation(
|
pub fn new_proof_validation(
|
||||||
@ -138,14 +115,7 @@ impl StorageTransaction {
|
|||||||
entry_height,
|
entry_height,
|
||||||
proof_mask,
|
proof_mask,
|
||||||
};
|
};
|
||||||
Transaction::new(
|
Transaction::new(from_keypair, &[], id(), &program, last_id, 0)
|
||||||
from_keypair,
|
|
||||||
&[Pubkey::new(&STORAGE_SYSTEM_ACCOUNT_ID)],
|
|
||||||
id(),
|
|
||||||
&program,
|
|
||||||
last_id,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_reward_claim(
|
pub fn new_reward_claim(
|
||||||
@ -154,13 +124,6 @@ impl StorageTransaction {
|
|||||||
entry_height: u64,
|
entry_height: u64,
|
||||||
) -> Transaction {
|
) -> Transaction {
|
||||||
let program = StorageProgram::ClaimStorageReward { entry_height };
|
let program = StorageProgram::ClaimStorageReward { entry_height };
|
||||||
Transaction::new(
|
Transaction::new(from_keypair, &[], id(), &program, last_id, 0)
|
||||||
from_keypair,
|
|
||||||
&[Pubkey::new(&STORAGE_SYSTEM_ACCOUNT_ID)],
|
|
||||||
id(),
|
|
||||||
&program,
|
|
||||||
last_id,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user