diff --git a/Cargo.lock b/Cargo.lock index a6b39c4f6b9606..c614701e1ed83b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2158,8 +2158,10 @@ version = "0.13.0" dependencies = [ "bincode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-runtime 0.13.0", "solana-sdk 0.13.0", ] @@ -2167,14 +2169,9 @@ dependencies = [ name = "solana-budget-program" version = "0.13.0" dependencies = [ - "bincode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "solana-budget-api 0.13.0", "solana-logger 0.13.0", - "solana-runtime 0.13.0", "solana-sdk 0.13.0", ] @@ -2204,6 +2201,8 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-logger 0.13.0", + "solana-runtime 0.13.0", "solana-sdk 0.13.0", ] @@ -2211,14 +2210,9 @@ dependencies = [ name = "solana-config-program" version = "0.13.0" dependencies = [ - "bincode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "solana-config-api 0.13.0", "solana-logger 0.13.0", - "solana-metrics 0.13.0", - "solana-runtime 0.13.0", "solana-sdk 0.13.0", ] diff --git a/programs/budget_api/Cargo.toml b/programs/budget_api/Cargo.toml index 03f12373fb06b0..45e1b3e100becd 100644 --- a/programs/budget_api/Cargo.toml +++ b/programs/budget_api/Cargo.toml @@ -11,10 +11,14 @@ edition = "2018" [dependencies] bincode = "1.1.2" chrono = { version = "0.4.0", features = ["serde"] } +log = "0.4.2" serde = "1.0.89" serde_derive = "1.0.89" solana-sdk = { path = "../../sdk", version = "0.13.0" } +[dev-dependencies] +solana-runtime = { path = "../../runtime", version = "0.13.0" } + [lib] name = "solana_budget_api" crate-type = ["lib"] diff --git a/programs/budget_program/src/budget_processor.rs b/programs/budget_api/src/budget_processor.rs similarity index 97% rename from programs/budget_program/src/budget_processor.rs rename to programs/budget_api/src/budget_processor.rs index 916e9e2e785868..21718b69c298e5 100644 --- a/programs/budget_program/src/budget_processor.rs +++ b/programs/budget_api/src/budget_processor.rs @@ -1,10 +1,10 @@ //! budget program +use crate::budget_instruction::BudgetInstruction; +use crate::budget_state::{BudgetError, BudgetState}; +use crate::payment_plan::Witness; use bincode::{deserialize, serialize}; use chrono::prelude::{DateTime, Utc}; use log::*; -use solana_budget_api::budget_instruction::BudgetInstruction; -use solana_budget_api::budget_state::{BudgetError, BudgetState}; -use solana_budget_api::payment_plan::Witness; use solana_sdk::account::KeyedAccount; use solana_sdk::pubkey::Pubkey; use solana_sdk::transaction::InstructionError; @@ -143,9 +143,9 @@ pub fn process_instruction( #[cfg(test)] mod test { use super::*; - use solana_budget_api::budget_instruction::BudgetInstruction; - use solana_budget_api::budget_script::BudgetScript; - use solana_budget_api::id; + use crate::budget_instruction::BudgetInstruction; + use crate::budget_script::BudgetScript; + use crate::id; use solana_runtime::bank::Bank; use solana_runtime::bank_client::BankClient; use solana_sdk::genesis_block::GenesisBlock; diff --git a/programs/budget_api/src/lib.rs b/programs/budget_api/src/lib.rs index 73c3f88f1079ea..034f2f3d4ac616 100644 --- a/programs/budget_api/src/lib.rs +++ b/programs/budget_api/src/lib.rs @@ -1,5 +1,6 @@ pub mod budget_expr; pub mod budget_instruction; +pub mod budget_processor; pub mod budget_script; pub mod budget_state; pub mod budget_transaction; diff --git a/programs/budget_program/Cargo.toml b/programs/budget_program/Cargo.toml index 76b7c72595b896..add775c30c4ac3 100644 --- a/programs/budget_program/Cargo.toml +++ b/programs/budget_program/Cargo.toml @@ -9,18 +9,11 @@ homepage = "https://solana.com/" edition = "2018" [dependencies] -bincode = "1.1.2" -chrono = { version = "0.4.0", features = ["serde"] } log = "0.4.2" -serde = "1.0.89" -serde_derive = "1.0.89" solana-budget-api = { path = "../budget_api", version = "0.13.0" } solana-logger = { path = "../../logger", version = "0.13.0" } solana-sdk = { path = "../../sdk", version = "0.13.0" } -[dev-dependencies] -solana-runtime = { path = "../../runtime", version = "0.13.0" } - [lib] name = "solana_budget_program" crate-type = ["cdylib"] diff --git a/programs/budget_program/src/lib.rs b/programs/budget_program/src/lib.rs index 6cf66ffe41daf2..dee532b62e57c2 100644 --- a/programs/budget_program/src/lib.rs +++ b/programs/budget_program/src/lib.rs @@ -1,5 +1,3 @@ -mod budget_processor; - -use crate::budget_processor::process_instruction; +use solana_budget_api::budget_processor::process_instruction; solana_sdk::process_instruction_entrypoint!(process_instruction); diff --git a/programs/config_api/Cargo.toml b/programs/config_api/Cargo.toml index 7c468de397b1fc..11ef00aa11a39d 100644 --- a/programs/config_api/Cargo.toml +++ b/programs/config_api/Cargo.toml @@ -13,8 +13,12 @@ bincode = "1.1.2" log = "0.4.2" serde = "1.0.89" serde_derive = "1.0.89" +solana-logger = { path = "../../logger", version = "0.13.0" } solana-sdk = { path = "../../sdk", version = "0.13.0" } +[dev-dependencies] +solana-runtime = { path = "../../runtime", version = "0.13.0" } + [lib] name = "solana_config_api" crate-type = ["lib"] diff --git a/programs/config_api/src/config_processor.rs b/programs/config_api/src/config_processor.rs new file mode 100644 index 00000000000000..c24dd7a1997508 --- /dev/null +++ b/programs/config_api/src/config_processor.rs @@ -0,0 +1,163 @@ +//! Config program + +use log::*; +use solana_sdk::account::KeyedAccount; +use solana_sdk::pubkey::Pubkey; +use solana_sdk::transaction::InstructionError; + +pub fn process_instruction( + _program_id: &Pubkey, + keyed_accounts: &mut [KeyedAccount], + data: &[u8], + _tick_height: u64, +) -> Result<(), InstructionError> { + if keyed_accounts[1].signer_key().is_none() { + error!("account[1] should sign the transaction"); + Err(InstructionError::MissingRequiredSignature)?; + } + + if keyed_accounts[1].account.data.len() < data.len() { + error!("instruction data too large"); + Err(InstructionError::InvalidInstructionData)?; + } + + keyed_accounts[1].account.data[0..data.len()].copy_from_slice(data); + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{id, ConfigInstruction, ConfigState}; + use bincode::{deserialize, serialized_size}; + use serde_derive::{Deserialize, Serialize}; + use solana_runtime::bank::Bank; + use solana_runtime::bank_client::BankClient; + use solana_sdk::genesis_block::GenesisBlock; + use solana_sdk::script::Script; + use solana_sdk::signature::{Keypair, KeypairUtil}; + use solana_sdk::system_instruction::SystemInstruction; + + #[derive(Serialize, Deserialize, Default, Debug, PartialEq)] + struct MyConfig { + pub item: u64, + } + impl MyConfig { + pub fn new(item: u64) -> Self { + Self { item } + } + pub fn deserialize(input: &[u8]) -> Option { + deserialize(input).ok() + } + } + + impl ConfigState for MyConfig { + fn max_space() -> u64 { + serialized_size(&Self::default()).unwrap() + } + } + + fn create_bank(lamports: u64) -> (Bank, Keypair) { + let (genesis_block, mint_keypair) = GenesisBlock::new(lamports); + let mut bank = Bank::new(&genesis_block); + bank.add_instruction_processor(id(), process_instruction); + (bank, mint_keypair) + } + + fn create_config_client(bank: &Bank, mint_keypair: Keypair) -> (BankClient, Pubkey, Pubkey) { + let config_client = + BankClient::new_with_keypairs(&bank, vec![Keypair::new(), Keypair::new()]); + + let from_pubkey = config_client.pubkeys()[0]; + let config_pubkey = config_client.pubkeys()[1]; + + let mint_client = BankClient::new(&bank, mint_keypair); + mint_client + .process_instruction(SystemInstruction::new_move( + &mint_client.pubkey(), + &from_pubkey, + 42, + )) + .expect("new_move"); + + mint_client + .process_instruction(ConfigInstruction::new_account::( + &mint_client.pubkey(), + &config_pubkey, + 1, + )) + .expect("new_account"); + + (config_client, from_pubkey, config_pubkey) + } + + #[test] + fn test_process_create_ok() { + solana_logger::setup(); + let (bank, from_keypair) = create_bank(10_000); + let (config_client, _, _) = create_config_client(&bank, from_keypair); + let config_account = bank.get_account(&config_client.pubkeys()[1]).unwrap(); + assert_eq!(id(), config_account.owner); + assert_eq!( + MyConfig::default(), + MyConfig::deserialize(&config_account.data).unwrap() + ); + } + + #[test] + fn test_process_store_ok() { + solana_logger::setup(); + let (bank, mint_keypair) = create_bank(10_000); + let (config_client, from_pubkey, config_pubkey) = create_config_client(&bank, mint_keypair); + + let my_config = MyConfig::new(42); + let instruction = ConfigInstruction::new_store(&from_pubkey, &config_pubkey, &my_config); + config_client.process_instruction(instruction).unwrap(); + + let config_account = bank.get_account(&config_pubkey).unwrap(); + assert_eq!( + my_config, + MyConfig::deserialize(&config_account.data).unwrap() + ); + } + + #[test] + fn test_process_store_fail_instruction_data_too_large() { + solana_logger::setup(); + let (bank, mint_keypair) = create_bank(10_000); + let (config_client, from_pubkey, config_pubkey) = create_config_client(&bank, mint_keypair); + + let my_config = MyConfig::new(42); + let instruction = ConfigInstruction::new_store(&from_pubkey, &config_pubkey, &my_config); + + // Replace instruction data with a vector that's too large + let script = Script::new(vec![instruction]); + let mut transaction = script.compile(); + transaction.instructions[0].data = vec![0; 123]; + config_client.process_transaction(transaction).unwrap_err(); + } + + #[test] + fn test_process_store_fail_account1_not_signer() { + solana_logger::setup(); + let (bank, mint_keypair) = create_bank(10_000); + let system_keypair = Keypair::new(); + let system_pubkey = system_keypair.pubkey(); + bank.transfer(42, &mint_keypair, &system_pubkey, bank.last_blockhash()) + .unwrap(); + let (_config_client, from_pubkey, config_pubkey) = + create_config_client(&bank, mint_keypair); + + let move_instruction = SystemInstruction::new_move(&system_pubkey, &Pubkey::default(), 42); + let my_config = MyConfig::new(42); + let store_instruction = + ConfigInstruction::new_store(&from_pubkey, &config_pubkey, &my_config); + + // Don't sign the transaction with `config_client` + let script = Script::new(vec![move_instruction, store_instruction]); + let mut transaction = script.compile(); + transaction.sign_unchecked(&[&system_keypair], bank.last_blockhash()); + let system_client = BankClient::new(&bank, system_keypair); + system_client.process_transaction(transaction).unwrap_err(); + } +} diff --git a/programs/config_api/src/lib.rs b/programs/config_api/src/lib.rs index e965d7830c24d5..127c314849c60d 100644 --- a/programs/config_api/src/lib.rs +++ b/programs/config_api/src/lib.rs @@ -2,6 +2,7 @@ use serde::Serialize; use solana_sdk::pubkey::Pubkey; mod config_instruction; +pub mod config_processor; pub use config_instruction::ConfigInstruction; diff --git a/programs/config_program/Cargo.toml b/programs/config_program/Cargo.toml index 588c784fbc8bb1..33c8a3d1b26401 100644 --- a/programs/config_program/Cargo.toml +++ b/programs/config_program/Cargo.toml @@ -10,17 +10,9 @@ edition = "2018" [dependencies] log = "0.4.2" -solana-logger = { path = "../../logger", version = "0.13.0" } -solana-metrics = { path = "../../metrics", version = "0.13.0" } -solana-sdk = { path = "../../sdk", version = "0.13.0" } solana-config-api = { path = "../config_api", version = "0.13.0" } - -[dev-dependencies] -bincode = "1.1.2" -serde = "1.0.89" -serde_derive = "1.0.89" solana-logger = { path = "../../logger", version = "0.13.0" } -solana-runtime = { path = "../../runtime", version = "0.13.0" } +solana-sdk = { path = "../../sdk", version = "0.13.0" } [lib] name = "solana_config_program" diff --git a/programs/config_program/src/lib.rs b/programs/config_program/src/lib.rs index 9120d640dacfe9..4af3e790e1b630 100644 --- a/programs/config_program/src/lib.rs +++ b/programs/config_program/src/lib.rs @@ -1,164 +1,3 @@ -//! Config program - -use log::*; -use solana_sdk::account::KeyedAccount; -use solana_sdk::pubkey::Pubkey; -use solana_sdk::transaction::InstructionError; +use solana_config_api::config_processor::process_instruction; solana_sdk::process_instruction_entrypoint!(process_instruction); -fn process_instruction( - _program_id: &Pubkey, - keyed_accounts: &mut [KeyedAccount], - data: &[u8], - _tick_height: u64, -) -> Result<(), InstructionError> { - if keyed_accounts[1].signer_key().is_none() { - error!("account[1] should sign the transaction"); - Err(InstructionError::MissingRequiredSignature)?; - } - - if keyed_accounts[1].account.data.len() < data.len() { - error!("instruction data too large"); - Err(InstructionError::InvalidInstructionData)?; - } - - keyed_accounts[1].account.data[0..data.len()].copy_from_slice(data); - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - use bincode::{deserialize, serialized_size}; - use serde_derive::{Deserialize, Serialize}; - use solana_config_api::{id, ConfigInstruction, ConfigState}; - use solana_runtime::bank::Bank; - use solana_runtime::bank_client::BankClient; - use solana_sdk::genesis_block::GenesisBlock; - use solana_sdk::script::Script; - use solana_sdk::signature::{Keypair, KeypairUtil}; - use solana_sdk::system_instruction::SystemInstruction; - - #[derive(Serialize, Deserialize, Default, Debug, PartialEq)] - struct MyConfig { - pub item: u64, - } - impl MyConfig { - pub fn new(item: u64) -> Self { - Self { item } - } - pub fn deserialize(input: &[u8]) -> Option { - deserialize(input).ok() - } - } - - impl ConfigState for MyConfig { - fn max_space() -> u64 { - serialized_size(&Self::default()).unwrap() - } - } - - fn create_bank(lamports: u64) -> (Bank, Keypair) { - let (genesis_block, mint_keypair) = GenesisBlock::new(lamports); - let mut bank = Bank::new(&genesis_block); - bank.add_instruction_processor(id(), process_instruction); - (bank, mint_keypair) - } - - fn create_config_client(bank: &Bank, mint_keypair: Keypair) -> (BankClient, Pubkey, Pubkey) { - let config_client = - BankClient::new_with_keypairs(&bank, vec![Keypair::new(), Keypair::new()]); - - let from_pubkey = config_client.pubkeys()[0]; - let config_pubkey = config_client.pubkeys()[1]; - - let mint_client = BankClient::new(&bank, mint_keypair); - mint_client - .process_instruction(SystemInstruction::new_move( - &mint_client.pubkey(), - &from_pubkey, - 42, - )) - .expect("new_move"); - - mint_client - .process_instruction(ConfigInstruction::new_account::( - &mint_client.pubkey(), - &config_pubkey, - 1, - )) - .expect("new_account"); - - (config_client, from_pubkey, config_pubkey) - } - - #[test] - fn test_process_create_ok() { - solana_logger::setup(); - let (bank, from_keypair) = create_bank(10_000); - let (config_client, _, _) = create_config_client(&bank, from_keypair); - let config_account = bank.get_account(&config_client.pubkeys()[1]).unwrap(); - assert_eq!(id(), config_account.owner); - assert_eq!( - MyConfig::default(), - MyConfig::deserialize(&config_account.data).unwrap() - ); - } - - #[test] - fn test_process_store_ok() { - solana_logger::setup(); - let (bank, mint_keypair) = create_bank(10_000); - let (config_client, from_pubkey, config_pubkey) = create_config_client(&bank, mint_keypair); - - let my_config = MyConfig::new(42); - let instruction = ConfigInstruction::new_store(&from_pubkey, &config_pubkey, &my_config); - config_client.process_instruction(instruction).unwrap(); - - let config_account = bank.get_account(&config_pubkey).unwrap(); - assert_eq!( - my_config, - MyConfig::deserialize(&config_account.data).unwrap() - ); - } - - #[test] - fn test_process_store_fail_instruction_data_too_large() { - solana_logger::setup(); - let (bank, mint_keypair) = create_bank(10_000); - let (config_client, from_pubkey, config_pubkey) = create_config_client(&bank, mint_keypair); - - let my_config = MyConfig::new(42); - let instruction = ConfigInstruction::new_store(&from_pubkey, &config_pubkey, &my_config); - - // Replace instruction data with a vector that's too large - let script = Script::new(vec![instruction]); - let mut transaction = script.compile(); - transaction.instructions[0].data = vec![0; 123]; - config_client.process_transaction(transaction).unwrap_err(); - } - - #[test] - fn test_process_store_fail_account1_not_signer() { - solana_logger::setup(); - let (bank, mint_keypair) = create_bank(10_000); - let system_keypair = Keypair::new(); - let system_pubkey = system_keypair.pubkey(); - bank.transfer(42, &mint_keypair, &system_pubkey, bank.last_blockhash()) - .unwrap(); - let (_config_client, from_pubkey, config_pubkey) = - create_config_client(&bank, mint_keypair); - - let move_instruction = SystemInstruction::new_move(&system_pubkey, &Pubkey::default(), 42); - let my_config = MyConfig::new(42); - let store_instruction = - ConfigInstruction::new_store(&from_pubkey, &config_pubkey, &my_config); - - // Don't sign the transaction with `config_client` - let script = Script::new(vec![move_instruction, store_instruction]); - let mut transaction = script.compile(); - transaction.sign_unchecked(&[&system_keypair], bank.last_blockhash()); - let system_client = BankClient::new(&bank, system_keypair); - system_client.process_transaction(transaction).unwrap_err(); - } -}