diff --git a/Cargo.lock b/Cargo.lock index 3c6515dd8..7b1082271 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1762,6 +1762,7 @@ dependencies = [ "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "solana-bpfloader 0.11.0", + "solana-budget-program 0.11.0", "solana-drone 0.11.0", "solana-erc20 0.11.0", "solana-jsonrpc-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1806,6 +1807,19 @@ dependencies = [ "solana_rbpf 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "solana-budget-program" +version = "0.11.0" +dependencies = [ + "bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (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.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-sdk 0.11.0", +] + [[package]] name = "solana-drone" version = "0.11.0" @@ -1949,6 +1963,7 @@ dependencies = [ "bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1987,6 +2002,7 @@ name = "solana-vote-program" version = "0.11.0" dependencies = [ "bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (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.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 8a2ff2197..142453373 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -98,6 +98,7 @@ serde_json = "1.0.10" sha2 = "0.8.0" socket2 = "0.3.8" solana-bpfloader = { path = "programs/native/bpf_loader", version = "0.11.0" } +solana-budget-program = { path = "programs/native/budget", version = "0.11.0" } solana-drone = { path = "drone", version = "0.11.0" } solana-erc20 = { path = "programs/native/erc20", version = "0.11.0" } solana-jsonrpc-core = "0.3.0" @@ -148,6 +149,7 @@ members = [ "sdk", "programs/bpf/rust/noop", "programs/native/bpf_loader", + "programs/native/budget", "programs/native/erc20", "programs/native/lua_loader", "programs/native/noop", diff --git a/programs/native/budget/Cargo.toml b/programs/native/budget/Cargo.toml new file mode 100644 index 000000000..506c5590a --- /dev/null +++ b/programs/native/budget/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "solana-budget-program" +version = "0.11.0" +description = "Solana budget program" +authors = ["Solana Maintainers "] +repository = "https://github.com/solana-labs/solana" +license = "Apache-2.0" + +[dependencies] +bincode = "1.0.0" +chrono = { version = "0.4.0", features = ["serde"] } +env_logger = "0.6.0" +log = "0.4.2" +serde = "1.0.27" +serde_derive = "1.0.27" +solana-sdk = { path = "../../../sdk", version = "0.11.0" } + +[lib] +name = "solana_budget_program" +crate-type = ["cdylib"] + diff --git a/src/budget_program.rs b/programs/native/budget/src/budget_program.rs similarity index 72% rename from src/budget_program.rs rename to programs/native/budget/src/budget_program.rs index e2184ae5e..eb9b5d594 100644 --- a/src/budget_program.rs +++ b/programs/native/budget/src/budget_program.rs @@ -1,13 +1,10 @@ //! budget program use bincode::{self, deserialize, serialize_into, serialized_size}; -use budget_expr::BudgetExpr; -use budget_instruction::Instruction; use chrono::prelude::{DateTime, Utc}; -use payment_plan::Witness; -use solana_sdk::account::Account; -use solana_sdk::native_program::ProgramError; -use solana_sdk::pubkey::Pubkey; -use solana_sdk::transaction::Transaction; +use solana_sdk::account::KeyedAccount; +use solana_sdk::budget_expr::BudgetExpr; +use solana_sdk::budget_instruction::Instruction; +use solana_sdk::payment_plan::Witness; use std::io; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] @@ -31,26 +28,11 @@ pub struct BudgetProgram { pub pending_budget: Option, } -const BUDGET_PROGRAM_ID: [u8; 32] = [ - 129, 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 id() -> Pubkey { - Pubkey::new(&BUDGET_PROGRAM_ID) -} - -pub fn check_id(program_id: &Pubkey) -> bool { - program_id.as_ref() == BUDGET_PROGRAM_ID -} - fn apply_debits( - tx: &Transaction, - instruction_index: usize, - accounts: &mut [&mut Account], + keyed_accounts: &mut [KeyedAccount], instruction: &Instruction, ) -> Result<(), BudgetError> { - if !accounts[0].userdata.is_empty() { + if !keyed_accounts[0].account.userdata.is_empty() { trace!("source is pending"); return Err(BudgetError::SourceIsPendingContract); } @@ -58,25 +40,26 @@ fn apply_debits( Instruction::NewBudget(expr) => { let expr = expr.clone(); if let Some(payment) = expr.final_payment() { - accounts[1].tokens += payment.tokens; + keyed_accounts[1].account.tokens += payment.tokens; Ok(()) } else { - let existing = BudgetProgram::deserialize(&accounts[1].userdata).ok(); + let existing = BudgetProgram::deserialize(&keyed_accounts[1].account.userdata).ok(); if Some(true) == existing.map(|x| x.initialized) { trace!("contract already exists"); Err(BudgetError::ContractAlreadyExists) } else { let mut program = BudgetProgram::default(); program.pending_budget = Some(expr); - accounts[1].tokens += accounts[0].tokens; - accounts[0].tokens = 0; + keyed_accounts[1].account.tokens += keyed_accounts[0].account.tokens; + keyed_accounts[0].account.tokens = 0; program.initialized = true; - program.serialize(&mut accounts[1].userdata) + program.serialize(&mut keyed_accounts[1].account.userdata) } } } Instruction::ApplyTimestamp(dt) => { - if let Ok(mut program) = BudgetProgram::deserialize(&accounts[1].userdata) { + if let Ok(mut program) = BudgetProgram::deserialize(&keyed_accounts[1].account.userdata) + { if !program.is_pending() { Err(BudgetError::ContractNotPending) } else if !program.initialized { @@ -84,16 +67,17 @@ fn apply_debits( Err(BudgetError::UninitializedContract) } else { trace!("apply timestamp"); - program.apply_timestamp(tx, instruction_index, accounts, *dt)?; + program.apply_timestamp(keyed_accounts, *dt)?; trace!("apply timestamp committed"); - program.serialize(&mut accounts[1].userdata) + program.serialize(&mut keyed_accounts[1].account.userdata) } } else { Err(BudgetError::UninitializedContract) } } Instruction::ApplySignature => { - if let Ok(mut program) = BudgetProgram::deserialize(&accounts[1].userdata) { + if let Ok(mut program) = BudgetProgram::deserialize(&keyed_accounts[1].account.userdata) + { if !program.is_pending() { Err(BudgetError::ContractNotPending) } else if !program.initialized { @@ -101,9 +85,9 @@ fn apply_debits( Err(BudgetError::UninitializedContract) } else { trace!("apply signature"); - program.apply_signature(tx, instruction_index, accounts)?; + program.apply_signature(keyed_accounts)?; trace!("apply signature committed"); - program.serialize(&mut accounts[1].userdata) + program.serialize(&mut keyed_accounts[1].account.userdata) } } else { Err(BudgetError::UninitializedContract) @@ -113,36 +97,24 @@ fn apply_debits( } /// Budget DSL contract interface -/// * tx - the transaction /// * accounts[0] - The source of the tokens /// * accounts[1] - The contract context. Once the contract has been completed, the tokens can /// be spent from this account . pub fn process_instruction( - tx: &Transaction, - instruction_index: usize, - accounts: &mut [&mut Account], + keyed_accounts: &mut [KeyedAccount], + data: &[u8], ) -> Result<(), BudgetError> { - if let Ok(instruction) = deserialize(tx.userdata(instruction_index)) { + if let Ok(instruction) = deserialize(data) { trace!("process_instruction: {:?}", instruction); - apply_debits(tx, instruction_index, accounts, &instruction) + apply_debits(keyed_accounts, &instruction) } else { - info!( - "Invalid transaction userdata: {:?}", - tx.userdata(instruction_index) - ); + info!("Invalid transaction userdata: {:?}", data); Err(BudgetError::UserdataDeserializeFailure) } } -pub fn process( - tx: &Transaction, - instruction_index: usize, - accounts: &mut [&mut Account], -) -> std::result::Result<(), ProgramError> { - process_instruction(&tx, instruction_index, accounts).map_err(|_| ProgramError::GenericError) -} - -//TODO the contract needs to provide a "get_balance" introspection call of the userdata +// TODO: Re-instate budget_program special case in bank.rs? +/* pub fn get_balance(account: &Account) -> u64 { if let Ok(program) = deserialize(&account.userdata) { let program: BudgetProgram = program; @@ -155,6 +127,7 @@ pub fn get_balance(account: &Account) -> u64 { account.tokens } } +*/ impl BudgetProgram { fn is_pending(&self) -> bool { @@ -162,15 +135,10 @@ impl BudgetProgram { } /// Process a Witness Signature. Any payment plans waiting on this signature /// will progress one step. - fn apply_signature( - &mut self, - tx: &Transaction, - instruction_index: usize, - accounts: &mut [&mut Account], - ) -> Result<(), BudgetError> { + fn apply_signature(&mut self, keyed_accounts: &mut [KeyedAccount]) -> Result<(), BudgetError> { let mut final_payment = None; if let Some(ref mut expr) = self.pending_budget { - let key = match tx.signer_key(instruction_index, 0) { + let key = match keyed_accounts[0].signer_key() { None => return Err(BudgetError::UnsignedKey), Some(key) => key, }; @@ -179,13 +147,13 @@ impl BudgetProgram { } if let Some(payment) = final_payment { - if Some(&payment.to) != tx.key(instruction_index, 2) { + if &payment.to != keyed_accounts[2].unsigned_key() { trace!("destination missing"); return Err(BudgetError::DestinationMissing); } self.pending_budget = None; - accounts[1].tokens -= payment.tokens; - accounts[2].tokens += payment.tokens; + keyed_accounts[1].account.tokens -= payment.tokens; + keyed_accounts[2].account.tokens += payment.tokens; } Ok(()) } @@ -194,16 +162,14 @@ impl BudgetProgram { /// will progress one step. fn apply_timestamp( &mut self, - tx: &Transaction, - instruction_index: usize, - accounts: &mut [&mut Account], + keyed_accounts: &mut [KeyedAccount], dt: DateTime, ) -> Result<(), BudgetError> { // Check to see if any timelocked transactions can be completed. let mut final_payment = None; if let Some(ref mut expr) = self.pending_budget { - let key = match tx.signer_key(instruction_index, 0) { + let key = match keyed_accounts[0].signer_key() { None => return Err(BudgetError::UnsignedKey), Some(key) => key, }; @@ -212,13 +178,13 @@ impl BudgetProgram { } if let Some(payment) = final_payment { - if Some(&payment.to) != tx.key(instruction_index, 2) { + if &payment.to != keyed_accounts[2].unsigned_key() { trace!("destination missing"); return Err(BudgetError::DestinationMissing); } self.pending_budget = None; - accounts[1].tokens -= payment.tokens; - accounts[2].tokens += payment.tokens; + keyed_accounts[1].account.tokens -= payment.tokens; + keyed_accounts[2].account.tokens += payment.tokens; } Ok(()) } @@ -259,22 +225,40 @@ impl BudgetProgram { deserialize(&input[8..8 + len as usize]) } } + #[cfg(test)] mod test { use super::*; use bincode::serialize; - use budget_transaction::BudgetTransaction; - use chrono::prelude::{DateTime, NaiveDate, Utc}; - use signature::GenKeys; use solana_sdk::account::Account; + use solana_sdk::budget_program::*; + use solana_sdk::budget_transaction::BudgetTransaction; use solana_sdk::hash::Hash; - use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; - use solana_sdk::transaction::Transaction; + use solana_sdk::transaction::{Instruction, Transaction}; - fn process_transaction(tx: &Transaction, accounts: &mut [Account]) -> Result<(), BudgetError> { - let mut refs: Vec<&mut Account> = accounts.iter_mut().collect(); - super::process_instruction(&tx, 0, &mut refs[..]) + fn process_transaction( + tx: &Transaction, + program_accounts: &mut [Account], + ) -> Result<(), BudgetError> { + assert_eq!(tx.instructions.len(), 1); + let Instruction { + ref accounts, + ref userdata, + .. + } = tx.instructions[0]; + + let mut keyed_accounts: Vec<_> = accounts + .iter() + .map(|&index| { + let index = index as usize; + let key = &tx.account_keys[index]; + (key, index < tx.signatures.len()) + }).zip(program_accounts.iter_mut()) + .map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account)) + .collect(); + + super::process_instruction(&mut keyed_accounts, &userdata) } #[test] fn test_serializer() { @@ -574,77 +558,4 @@ mod test { // Success if there was no panic... } - - /// Detect binary changes in the serialized contract userdata, which could have a downstream - /// affect on SDKs and DApps - #[test] - fn test_sdk_serialize() { - let keypair = &GenKeys::new([0u8; 32]).gen_n_keypairs(1)[0]; - let to = Pubkey::new(&[ - 1, 1, 1, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 6, 5, 4, - 1, 1, 1, - ]); - let contract = Pubkey::new(&[ - 2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4, - 2, 2, 2, - ]); - let date = - DateTime::::from_utc(NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11), Utc); - let date_iso8601 = "2016-07-08T09:10:11Z"; - - let tx = Transaction::budget_new(&keypair, to, 192, Hash::default()); - assert_eq!( - tx.userdata(0).to_vec(), - vec![2, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0] - ); - assert_eq!( - tx.userdata(1).to_vec(), - vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 4, 5, 6, 7, 8, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 6, 5, 4, 1, 1, 1 - ] - ); - - let tx = Transaction::budget_new_on_date( - &keypair, - to, - contract, - date, - keypair.pubkey(), - Some(keypair.pubkey()), - 192, - Hash::default(), - ); - assert_eq!( - tx.userdata(0).to_vec(), - vec![ - 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 50, 48, 49, 54, 45, - 48, 55, 45, 48, 56, 84, 48, 57, 58, 49, 48, 58, 49, 49, 90, 32, 253, 186, 201, 177, - 11, 117, 135, 187, 167, 181, 188, 22, 59, 206, 105, 231, 150, 215, 30, 78, 212, 76, - 16, 252, 180, 72, 134, 137, 247, 161, 68, 192, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 4, 5, - 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 6, 5, 4, 1, 1, 1, 1, - 0, 0, 0, 32, 253, 186, 201, 177, 11, 117, 135, 187, 167, 181, 188, 22, 59, 206, - 105, 231, 150, 215, 30, 78, 212, 76, 16, 252, 180, 72, 134, 137, 247, 161, 68, 192, - 0, 0, 0, 0, 0, 0, 0, 32, 253, 186, 201, 177, 11, 117, 135, 187, 167, 181, 188, 22, - 59, 206, 105, 231, 150, 215, 30, 78, 212, 76, 16, 252, 180, 72, 134, 137, 247, 161, - 68 - ] - ); - - // ApplyTimestamp(date) - let tx = Transaction::budget_new_timestamp( - &keypair, - keypair.pubkey(), - to, - date, - Hash::default(), - ); - let mut expected_userdata = vec![1, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0]; - expected_userdata.extend(date_iso8601.as_bytes()); - assert_eq!(tx.userdata(0).to_vec(), expected_userdata); - - // ApplySignature - let tx = Transaction::budget_new_signature(&keypair, keypair.pubkey(), to, Hash::default()); - assert_eq!(tx.userdata(0).to_vec(), vec![2, 0, 0, 0]); - } } diff --git a/programs/native/budget/src/lib.rs b/programs/native/budget/src/lib.rs new file mode 100644 index 000000000..84ec7aea8 --- /dev/null +++ b/programs/native/budget/src/lib.rs @@ -0,0 +1,36 @@ +extern crate bincode; +extern crate chrono; +extern crate env_logger; +#[macro_use] +extern crate log; +#[macro_use] +extern crate serde_derive; +#[macro_use] +extern crate solana_sdk; + +mod budget_program; + +use solana_sdk::account::KeyedAccount; +use solana_sdk::native_program::ProgramError; +use solana_sdk::pubkey::Pubkey; +use std::sync::{Once, ONCE_INIT}; + +use budget_program::process_instruction; + +solana_entrypoint!(entrypoint); +fn entrypoint( + _program_id: &Pubkey, + keyed_accounts: &mut [KeyedAccount], + data: &[u8], + _tick_height: u64, +) -> Result<(), ProgramError> { + static INIT: Once = ONCE_INIT; + INIT.call_once(|| { + // env_logger can only be initialized once + env_logger::init(); + }); + + trace!("process_instruction: {:?}", data); + trace!("keyed_accounts: {:?}", keyed_accounts); + process_instruction(keyed_accounts, data).map_err(|_| ProgramError::GenericError) +} diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index d869c0fb6..4a37c5ba3 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -10,6 +10,7 @@ license = "Apache-2.0" bincode = "1.0.0" byteorder = "1.2.1" bs58 = "0.2.0" +chrono = { version = "0.4.0", features = ["serde"] } generic-array = { version = "0.12.0", default-features = false, features = ["serde"] } log = "0.4.2" ring = "0.13.2" diff --git a/src/budget_expr.rs b/sdk/src/budget_expr.rs similarity index 99% rename from src/budget_expr.rs rename to sdk/src/budget_expr.rs index 8d2b5ef19..8c2cfad5e 100644 --- a/src/budget_expr.rs +++ b/sdk/src/budget_expr.rs @@ -5,7 +5,7 @@ use chrono::prelude::*; use payment_plan::{Payment, Witness}; -use solana_sdk::pubkey::Pubkey; +use pubkey::Pubkey; use std::mem; /// A data type representing a `Witness` that the payment plan is waiting on. @@ -141,7 +141,7 @@ impl BudgetExpr { #[cfg(test)] mod tests { use super::*; - use solana_sdk::signature::{Keypair, KeypairUtil}; + use signature::{Keypair, KeypairUtil}; #[test] fn test_signature_satisfied() { diff --git a/src/budget_instruction.rs b/sdk/src/budget_instruction.rs similarity index 100% rename from src/budget_instruction.rs rename to sdk/src/budget_instruction.rs diff --git a/sdk/src/budget_program.rs b/sdk/src/budget_program.rs new file mode 100644 index 000000000..6854b482e --- /dev/null +++ b/sdk/src/budget_program.rs @@ -0,0 +1,14 @@ +use pubkey::Pubkey; + +pub const BUDGET_PROGRAM_ID: [u8; 32] = [ + 129, 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 id() -> Pubkey { + Pubkey::new(&BUDGET_PROGRAM_ID) +} + +pub fn check_id(program_id: &Pubkey) -> bool { + program_id.as_ref() == BUDGET_PROGRAM_ID +} diff --git a/src/budget_transaction.rs b/sdk/src/budget_transaction.rs similarity index 97% rename from src/budget_transaction.rs rename to sdk/src/budget_transaction.rs index 808a720f1..fa4c1873f 100644 --- a/src/budget_transaction.rs +++ b/sdk/src/budget_transaction.rs @@ -5,14 +5,13 @@ use budget_expr::{BudgetExpr, Condition}; use budget_instruction::Instruction; use budget_program; use chrono::prelude::*; +use hash::Hash; use payment_plan::Payment; -use solana_sdk::hash::Hash; -use solana_sdk::pubkey::Pubkey; -use solana_sdk::signature::{Keypair, KeypairUtil}; -use solana_sdk::system_instruction::SystemInstruction; -use solana_sdk::system_program; - -use solana_sdk::transaction::{self, Transaction}; +use pubkey::Pubkey; +use signature::{Keypair, KeypairUtil}; +use system_instruction::SystemInstruction; +use system_program; +use transaction::{self, Transaction}; pub trait BudgetTransaction { fn budget_new_taxed( diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index aa8b9b5c7..46d2518e2 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -1,10 +1,15 @@ pub mod account; pub mod bpf_loader; +pub mod budget_expr; +pub mod budget_instruction; +pub mod budget_program; +pub mod budget_transaction; pub mod hash; pub mod loader_instruction; pub mod native_loader; pub mod native_program; pub mod packet; +pub mod payment_plan; pub mod pubkey; pub mod signature; pub mod storage_program; @@ -18,6 +23,7 @@ pub mod vote_program; extern crate bincode; extern crate bs58; extern crate byteorder; +extern crate chrono; extern crate generic_array; extern crate log; extern crate ring; diff --git a/src/payment_plan.rs b/sdk/src/payment_plan.rs similarity index 96% rename from src/payment_plan.rs rename to sdk/src/payment_plan.rs index c0f5f1e65..08208829a 100644 --- a/src/payment_plan.rs +++ b/sdk/src/payment_plan.rs @@ -4,7 +4,7 @@ //! `Payment`, the payment is executed. use chrono::prelude::*; -use solana_sdk::pubkey::Pubkey; +use pubkey::Pubkey; /// The types of events a payment plan can process. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] diff --git a/src/bank.rs b/src/bank.rs index be33cd2cc..74cc6a8b5 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -5,7 +5,6 @@ use bincode::deserialize; use bincode::serialize; -use budget_program; use counter::Counter; use entry::Entry; use itertools::Itertools; @@ -15,7 +14,6 @@ use ledger::Block; use log::Level; use mint::Mint; use native_loader; -use payment_plan::Payment; use poh_recorder::PohRecorder; use poh_service::NUM_TICKS_PER_SECOND; use rayon::prelude::*; @@ -23,8 +21,10 @@ use rpc::RpcSignatureStatus; use runtime::{self, RuntimeError}; use solana_sdk::account::Account; use solana_sdk::bpf_loader; +use solana_sdk::budget_program; use solana_sdk::hash::{hash, Hash}; use solana_sdk::native_program::ProgramError; +use solana_sdk::payment_plan::Payment; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::Keypair; use solana_sdk::signature::Signature; @@ -448,6 +448,16 @@ impl Bank { accounts.store(&bpf_loader::id(), &bpf_loader_account); + // Budget program + let budget_program_account = Account { + tokens: 1, + owner: budget_program::id(), + userdata: b"solana_budget_program".to_vec(), + executable: true, + loader: native_loader::id(), + }; + accounts.store(&budget_program::id(), &budget_program_account); + // Erc20 token program let erc20_account = Account { tokens: 1, @@ -765,10 +775,6 @@ impl Bank { } fn load_executable_accounts(&self, mut program_id: Pubkey) -> Result> { - if runtime::is_legacy_program(&program_id) { - return Ok(vec![]); - } - let mut accounts = Vec::new(); let mut depth = 0; loop { @@ -1228,11 +1234,13 @@ impl Bank { } pub fn read_balance(account: &Account) -> u64 { + // TODO: Re-instate budget_program special case? + /* if budget_program::check_id(&account.owner) { - budget_program::get_balance(account) - } else { - account.tokens + return budget_program::get_balance(account); } + */ + account.tokens } /// Each program would need to be able to introspect its own state /// this is hard-coded to the Budget language diff --git a/src/entry.rs b/src/entry.rs index 054686365..da879bc98 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -272,9 +272,9 @@ pub fn reconstruct_entries_from_blobs(blobs: Vec) -> Result<(Vec Vec { mod tests { use super::*; use bincode::{deserialize, serialized_size}; - use budget_transaction::BudgetTransaction; use entry::{next_entry, reconstruct_entries_from_blobs, Entry}; use packet::{to_blobs, BLOB_DATA_SIZE, PACKET_DATA_SIZE}; use solana_sdk::hash::hash; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::transaction::Transaction; + use solana_sdk::vote_program::Vote; use std; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - use solana_sdk::vote_program::Vote; #[test] fn test_verify_slice() { diff --git a/src/lib.rs b/src/lib.rs index 1a01e4528..2a5c76035 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,9 +14,6 @@ pub mod banking_stage; pub mod blob_fetch_stage; pub mod bloom; pub mod broadcast_stage; -pub mod budget_expr; -pub mod budget_instruction; -pub mod budget_transaction; #[cfg(feature = "chacha")] pub mod chacha; #[cfg(all(feature = "chacha", feature = "cuda"))] @@ -31,7 +28,6 @@ pub mod crds_traits_impls; pub mod crds_value; #[macro_use] pub mod contact_info; -pub mod budget_program; pub mod cluster_info; pub mod compute_leader_finality_service; pub mod db_ledger; @@ -51,7 +47,6 @@ pub mod native_loader; pub mod ncp; pub mod netutil; pub mod packet; -pub mod payment_plan; pub mod poh; pub mod poh_recorder; pub mod poh_service; diff --git a/src/rpc_pubsub.rs b/src/rpc_pubsub.rs index 195c8c029..b306828b4 100644 --- a/src/rpc_pubsub.rs +++ b/src/rpc_pubsub.rs @@ -246,10 +246,10 @@ impl RpcSolPubSub for RpcSolPubSubImpl { #[cfg(test)] mod tests { use super::*; - use budget_program; - use budget_transaction::BudgetTransaction; use jsonrpc_core::futures::sync::mpsc; use mint::Mint; + use solana_sdk::budget_program; + use solana_sdk::budget_transaction::BudgetTransaction; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::transaction::Transaction; use std::net::{IpAddr, Ipv4Addr}; diff --git a/src/runtime.rs b/src/runtime.rs index 12cd187a7..642a27ccb 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -1,4 +1,3 @@ -use budget_program; use native_loader; use solana_sdk::account::{create_keyed_accounts, Account, KeyedAccount}; use solana_sdk::native_program::ProgramError; @@ -13,10 +12,6 @@ pub enum RuntimeError { ProgramError(u8, ProgramError), } -pub fn is_legacy_program(program_id: &Pubkey) -> bool { - budget_program::check_id(program_id) -} - /// Process an instruction /// This method calls the instruction's program entrypoint method fn process_instruction( @@ -28,36 +23,25 @@ fn process_instruction( ) -> Result<(), ProgramError> { let program_id = tx.program_id(instruction_index); - // Call the program method - // It's up to the program to implement its own rules on moving funds - if is_legacy_program(&program_id) { - if budget_program::check_id(&program_id) { - budget_program::process(&tx, instruction_index, program_accounts)?; - } else { - unreachable!(); - }; - Ok(()) - } else { - let mut keyed_accounts = create_keyed_accounts(executable_accounts); - let mut keyed_accounts2: Vec<_> = tx.instructions[instruction_index] - .accounts - .iter() - .map(|&index| { - let index = index as usize; - let key = &tx.account_keys[index]; - (key, index < tx.signatures.len()) - }).zip(program_accounts.iter_mut()) - .map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account)) - .collect(); - keyed_accounts.append(&mut keyed_accounts2); + let mut keyed_accounts = create_keyed_accounts(executable_accounts); + let mut keyed_accounts2: Vec<_> = tx.instructions[instruction_index] + .accounts + .iter() + .map(|&index| { + let index = index as usize; + let key = &tx.account_keys[index]; + (key, index < tx.signatures.len()) + }).zip(program_accounts.iter_mut()) + .map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account)) + .collect(); + keyed_accounts.append(&mut keyed_accounts2); - native_loader::process_instruction( - &program_id, - &mut keyed_accounts, - &tx.instructions[instruction_index].userdata, - tick_height, - ) - } + native_loader::process_instruction( + &program_id, + &mut keyed_accounts, + &tx.instructions[instruction_index].userdata, + tick_height, + ) } fn verify_instruction( diff --git a/src/sigverify.rs b/src/sigverify.rs index d0e4c447d..66e16baab 100644 --- a/src/sigverify.rs +++ b/src/sigverify.rs @@ -323,9 +323,9 @@ pub fn make_packet_from_transaction(tx: Transaction) -> Packet { #[cfg(test)] mod tests { use bincode::serialize; - use budget_program; use packet::{Packet, SharedPackets}; use sigverify; + use solana_sdk::budget_program; use solana_sdk::hash::Hash; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; diff --git a/src/wallet.rs b/src/wallet.rs index c1a065a6d..0ad379884 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -1,7 +1,5 @@ use bincode::serialize; use bs58; -use budget_program; -use budget_transaction::BudgetTransaction; use chrono::prelude::*; use clap::ArgMatches; use elf; @@ -14,6 +12,8 @@ use rpc_request::{get_rpc_request_str, RpcClient, RpcRequest}; use serde_json; use solana_drone::drone::{request_airdrop_transaction, DRONE_PORT}; use solana_sdk::bpf_loader; +use solana_sdk::budget_program; +use solana_sdk::budget_transaction::BudgetTransaction; use solana_sdk::hash::Hash; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil, Signature};