diff --git a/Cargo.lock b/Cargo.lock index 41740d6e33..6d39cee3a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3279,21 +3279,6 @@ dependencies = [ "solana-sdk 0.22.0", ] -[[package]] -name = "solana-config-tests" -version = "0.22.0" -dependencies = [ - "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-config-program 0.22.0", - "solana-logger 0.22.0", - "solana-runtime 0.22.0", - "solana-sdk 0.22.0", -] - [[package]] name = "solana-core" version = "0.22.0" @@ -3948,6 +3933,7 @@ dependencies = [ name = "solana-storage-program" version = "0.22.0" dependencies = [ + "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 5484ffb0a7..16b4eae228 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,6 @@ members = [ "programs/btc_spv", "programs/btc_spv_bin", "programs/config", - "programs/config_tests", "programs/exchange", "programs/failure", "programs/noop", diff --git a/programs/storage/Cargo.toml b/programs/storage/Cargo.toml index 592dbfc612..19fe94fc1a 100644 --- a/programs/storage/Cargo.toml +++ b/programs/storage/Cargo.toml @@ -19,6 +19,9 @@ serde_derive = "1.0.103" solana-logger = { path = "../../logger", version = "0.22.0" } solana-sdk = { path = "../../sdk", version = "0.22.0" } +[dev-dependencies] +assert_matches = "1.3.0" + [lib] crate-type = ["lib", "cdylib"] name = "solana_storage_program" diff --git a/programs/storage/src/storage_processor.rs b/programs/storage/src/storage_processor.rs index d0e7ed1735..49c5d155ee 100644 --- a/programs/storage/src/storage_processor.rs +++ b/programs/storage/src/storage_processor.rs @@ -94,3 +94,192 @@ pub fn process_instruction( } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + id, + storage_contract::STORAGE_ACCOUNT_SPACE, + storage_instruction::{self, StorageAccountType}, + }; + use log::*; + + use assert_matches::assert_matches; + use solana_sdk::{ + account::{create_keyed_accounts, Account, KeyedAccount}, + clock::DEFAULT_SLOTS_PER_SEGMENT, + hash::Hash, + instruction::{Instruction, InstructionError}, + signature::Signature, + sysvar::{ + clock::{self, Clock}, + Sysvar, + }, + }; + + fn test_instruction( + ix: &Instruction, + program_accounts: &mut [Account], + ) -> Result<(), InstructionError> { + let mut keyed_accounts: Vec<_> = ix + .accounts + .iter() + .zip(program_accounts.iter_mut()) + .map(|(account_meta, account)| { + KeyedAccount::new(&account_meta.pubkey, account_meta.is_signer, account) + }) + .collect(); + + let ret = process_instruction(&id(), &mut keyed_accounts, &ix.data); + info!("ret: {:?}", ret); + ret + } + + #[test] + fn test_proof_bounds() { + let account_owner = Pubkey::new_rand(); + let pubkey = Pubkey::new_rand(); + let mut account = Account { + data: vec![0; STORAGE_ACCOUNT_SPACE as usize], + ..Account::default() + }; + { + let mut storage_account = StorageAccount::new(pubkey, &mut account); + storage_account + .initialize_storage(account_owner, StorageAccountType::Archiver) + .unwrap(); + } + + let ix = storage_instruction::mining_proof( + &pubkey, + Hash::default(), + 0, + Signature::default(), + Hash::default(), + ); + // the proof is for segment 0, need to move the slot into segment 2 + let mut clock_account = clock::create_account(1, 0, 0, 0, 0); + Clock::to_account( + &Clock { + slot: DEFAULT_SLOTS_PER_SEGMENT * 2, + segment: 2, + ..Clock::default() + }, + &mut clock_account, + ); + + assert_eq!(test_instruction(&ix, &mut [account, clock_account]), Ok(())); + } + + #[test] + fn test_storage_tx() { + 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, &[]).is_err()); + } + + #[test] + fn test_serialize_overflow() { + let pubkey = Pubkey::new_rand(); + let clock_id = clock::id(); + let mut keyed_accounts = Vec::new(); + let mut user_account = Account::default(); + let mut clock_account = clock::create_account(1, 0, 0, 0, 0); + keyed_accounts.push(KeyedAccount::new(&pubkey, true, &mut user_account)); + keyed_accounts.push(KeyedAccount::new(&clock_id, false, &mut clock_account)); + + let ix = storage_instruction::advertise_recent_blockhash(&pubkey, Hash::default(), 1); + + assert_eq!( + process_instruction(&id(), &mut keyed_accounts, &ix.data), + Err(InstructionError::InvalidAccountData) + ); + } + + #[test] + fn test_invalid_accounts_len() { + let pubkey = Pubkey::new_rand(); + let mut accounts = [Account::default()]; + + let ix = storage_instruction::mining_proof( + &pubkey, + Hash::default(), + 0, + Signature::default(), + Hash::default(), + ); + // move tick height into segment 1 + let mut clock_account = clock::create_account(1, 0, 0, 0, 0); + Clock::to_account( + &Clock { + slot: 16, + segment: 1, + ..Clock::default() + }, + &mut clock_account, + ); + + assert!(test_instruction(&ix, &mut accounts).is_err()); + + let mut accounts = [Account::default(), clock_account, Account::default()]; + + assert!(test_instruction(&ix, &mut accounts).is_err()); + } + + #[test] + fn test_submit_mining_invalid_slot() { + 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); + accounts[1].data.resize(STORAGE_ACCOUNT_SPACE as usize, 0); + + let ix = storage_instruction::mining_proof( + &pubkey, + Hash::default(), + 0, + Signature::default(), + Hash::default(), + ); + + // submitting a proof for a slot in the past, so this should fail + assert!(test_instruction(&ix, &mut accounts).is_err()); + } + + #[test] + fn test_submit_mining_ok() { + solana_logger::setup(); + let account_owner = Pubkey::new_rand(); + let pubkey = Pubkey::new_rand(); + let mut account = Account::default(); + account.data.resize(STORAGE_ACCOUNT_SPACE as usize, 0); + { + let mut storage_account = StorageAccount::new(pubkey, &mut account); + storage_account + .initialize_storage(account_owner, StorageAccountType::Archiver) + .unwrap(); + } + + let ix = storage_instruction::mining_proof( + &pubkey, + Hash::default(), + 0, + Signature::default(), + Hash::default(), + ); + // move slot into segment 1 + let mut clock_account = clock::create_account(1, 0, 0, 0, 0); + Clock::to_account( + &Clock { + slot: DEFAULT_SLOTS_PER_SEGMENT, + segment: 1, + ..Clock::default() + }, + &mut clock_account, + ); + + assert_matches!(test_instruction(&ix, &mut [account, clock_account]), Ok(_)); + } +} diff --git a/programs/storage_tests/tests/storage_processor.rs b/programs/storage_tests/tests/storage_processor.rs index 276eada32c..44a50839c7 100644 --- a/programs/storage_tests/tests/storage_processor.rs +++ b/programs/storage_tests/tests/storage_processor.rs @@ -7,26 +7,22 @@ use solana_runtime::{ genesis_utils::{create_genesis_config, GenesisConfigInfo}, }; use solana_sdk::{ - account::{create_keyed_accounts, Account, KeyedAccount}, account_utils::State, client::SyncClient, clock::{get_segment_from_slot, DEFAULT_SLOTS_PER_SEGMENT, DEFAULT_TICKS_PER_SLOT}, hash::{hash, Hash}, - instruction::{Instruction, InstructionError}, message::Message, pubkey::Pubkey, signature::{Keypair, KeypairUtil, Signature}, system_instruction, sysvar::{ - clock::{self, Clock}, rewards::{self, Rewards}, Sysvar, }, }; use solana_storage_program::{ id, - storage_contract::StorageAccount, - storage_contract::{ProofStatus, StorageContract, STORAGE_ACCOUNT_SPACE}, + storage_contract::{ProofStatus, StorageContract}, storage_instruction::{self, StorageAccountType}, storage_processor::process_instruction, }; @@ -35,24 +31,6 @@ use std::sync::Arc; const TICKS_IN_SEGMENT: u64 = DEFAULT_SLOTS_PER_SEGMENT * DEFAULT_TICKS_PER_SLOT; -fn test_instruction( - ix: &Instruction, - program_accounts: &mut [Account], -) -> Result<(), InstructionError> { - let mut keyed_accounts: Vec<_> = ix - .accounts - .iter() - .zip(program_accounts.iter_mut()) - .map(|(account_meta, account)| { - KeyedAccount::new(&account_meta.pubkey, account_meta.is_signer, account) - }) - .collect(); - - let ret = process_instruction(&id(), &mut keyed_accounts, &ix.data); - info!("ret: {:?}", ret); - ret -} - #[test] fn test_account_owner() { let account_owner = Pubkey::new_rand(); @@ -113,153 +91,6 @@ fn test_account_owner() { } } -#[test] -fn test_proof_bounds() { - let account_owner = Pubkey::new_rand(); - let pubkey = Pubkey::new_rand(); - let mut account = Account { - data: vec![0; STORAGE_ACCOUNT_SPACE as usize], - ..Account::default() - }; - { - let mut storage_account = StorageAccount::new(pubkey, &mut account); - storage_account - .initialize_storage(account_owner, StorageAccountType::Archiver) - .unwrap(); - } - - let ix = storage_instruction::mining_proof( - &pubkey, - Hash::default(), - 0, - Signature::default(), - Hash::default(), - ); - // the proof is for segment 0, need to move the slot into segment 2 - let mut clock_account = clock::create_account(1, 0, 0, 0, 0); - Clock::to_account( - &Clock { - slot: DEFAULT_SLOTS_PER_SEGMENT * 2, - segment: 2, - ..Clock::default() - }, - &mut clock_account, - ); - - assert_eq!(test_instruction(&ix, &mut [account, clock_account]), Ok(())); -} - -#[test] -fn test_storage_tx() { - 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, &[]).is_err()); -} - -#[test] -fn test_serialize_overflow() { - let pubkey = Pubkey::new_rand(); - let clock_id = clock::id(); - let mut keyed_accounts = Vec::new(); - let mut user_account = Account::default(); - let mut clock_account = clock::create_account(1, 0, 0, 0, 0); - keyed_accounts.push(KeyedAccount::new(&pubkey, true, &mut user_account)); - keyed_accounts.push(KeyedAccount::new(&clock_id, false, &mut clock_account)); - - let ix = storage_instruction::advertise_recent_blockhash(&pubkey, Hash::default(), 1); - - assert_eq!( - process_instruction(&id(), &mut keyed_accounts, &ix.data), - Err(InstructionError::InvalidAccountData) - ); -} - -#[test] -fn test_invalid_accounts_len() { - let pubkey = Pubkey::new_rand(); - let mut accounts = [Account::default()]; - - let ix = storage_instruction::mining_proof( - &pubkey, - Hash::default(), - 0, - Signature::default(), - Hash::default(), - ); - // move tick height into segment 1 - let mut clock_account = clock::create_account(1, 0, 0, 0, 0); - Clock::to_account( - &Clock { - slot: 16, - segment: 1, - ..Clock::default() - }, - &mut clock_account, - ); - - assert!(test_instruction(&ix, &mut accounts).is_err()); - - let mut accounts = [Account::default(), clock_account, Account::default()]; - - assert!(test_instruction(&ix, &mut accounts).is_err()); -} - -#[test] -fn test_submit_mining_invalid_slot() { - 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); - accounts[1].data.resize(STORAGE_ACCOUNT_SPACE as usize, 0); - - let ix = storage_instruction::mining_proof( - &pubkey, - Hash::default(), - 0, - Signature::default(), - Hash::default(), - ); - - // submitting a proof for a slot in the past, so this should fail - assert!(test_instruction(&ix, &mut accounts).is_err()); -} - -#[test] -fn test_submit_mining_ok() { - solana_logger::setup(); - let account_owner = Pubkey::new_rand(); - let pubkey = Pubkey::new_rand(); - let mut account = Account::default(); - account.data.resize(STORAGE_ACCOUNT_SPACE as usize, 0); - { - let mut storage_account = StorageAccount::new(pubkey, &mut account); - storage_account - .initialize_storage(account_owner, StorageAccountType::Archiver) - .unwrap(); - } - - let ix = storage_instruction::mining_proof( - &pubkey, - Hash::default(), - 0, - Signature::default(), - Hash::default(), - ); - // move slot into segment 1 - let mut clock_account = clock::create_account(1, 0, 0, 0, 0); - Clock::to_account( - &Clock { - slot: DEFAULT_SLOTS_PER_SEGMENT, - segment: 1, - ..Clock::default() - }, - &mut clock_account, - ); - - assert_matches!(test_instruction(&ix, &mut [account, clock_account]), Ok(_)); -} - #[test] fn test_validate_mining() { solana_logger::setup();