diff --git a/Cargo.lock b/Cargo.lock index c42e00238..508210187 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1986,6 +1986,7 @@ dependencies = [ "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)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-budget-api 0.12.0", "solana-budget-program 0.12.0", "solana-drone 0.12.0", "solana-logger 0.12.0", @@ -2041,6 +2042,17 @@ dependencies = [ "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "solana-budget-api" +version = "0.12.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)", + "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-sdk 0.12.0", +] + [[package]] name = "solana-budget-program" version = "0.12.0" @@ -2050,6 +2062,7 @@ 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-budget-api 0.12.0", "solana-logger 0.12.0", "solana-sdk 0.12.0", ] @@ -2261,6 +2274,7 @@ dependencies = [ "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)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-budget-api 0.12.0", "solana-logger 0.12.0", "solana-metrics 0.12.0", "solana-native-loader 0.12.0", @@ -2371,6 +2385,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "solana 0.12.0", + "solana-budget-api 0.12.0", "solana-drone 0.12.0", "solana-logger 0.12.0", "solana-sdk 0.12.0", diff --git a/Cargo.toml b/Cargo.toml index 9e5adab0f..4ffe5cab2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,6 +73,7 @@ members = [ "programs", "programs/native/bpf_loader", "programs/native/budget", + "programs/native/budget_api", "programs/native/token", "programs/native/failure", "programs/native/native_loader", diff --git a/core/Cargo.toml b/core/Cargo.toml index d6d0df5cd..d161749fa 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -46,6 +46,7 @@ rocksdb = "0.11.0" serde = "1.0.89" serde_derive = "1.0.88" serde_json = "1.0.39" +solana-budget-api = { path = "../programs/native/budget_api", version = "0.12.0" } solana-drone = { path = "../drone", version = "0.12.0" } solana-logger = { path = "../logger", version = "0.12.0" } solana-metrics = { path = "../metrics", version = "0.12.0" } diff --git a/core/src/chacha.rs b/core/src/chacha.rs index 4c557c759..ef5dc8367 100644 --- a/core/src/chacha.rs +++ b/core/src/chacha.rs @@ -95,7 +95,7 @@ mod tests { use crate::chacha::chacha_cbc_encrypt_ledger; use crate::entry::Entry; use ring::signature::Ed25519KeyPair; - use solana_sdk::budget_transaction::BudgetTransaction; + use solana_budget_api::budget_transaction::BudgetTransaction; use solana_sdk::hash::{hash, Hash, Hasher}; use solana_sdk::signature::KeypairUtil; use std::fs::remove_file; diff --git a/core/src/entry.rs b/core/src/entry.rs index 47f4952ee..d06e42864 100644 --- a/core/src/entry.rs +++ b/core/src/entry.rs @@ -8,7 +8,7 @@ use crate::result::Result; use bincode::{deserialize, serialize_into, serialized_size}; use chrono::prelude::Utc; use rayon::prelude::*; -use solana_sdk::budget_transaction::BudgetTransaction; +use solana_budget_api::budget_transaction::BudgetTransaction; use solana_sdk::hash::Hash; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; diff --git a/core/src/rpc_pubsub.rs b/core/src/rpc_pubsub.rs index 2692ba188..81cb8784a 100644 --- a/core/src/rpc_pubsub.rs +++ b/core/src/rpc_pubsub.rs @@ -164,9 +164,9 @@ mod tests { use jsonrpc_core::futures::sync::mpsc; use jsonrpc_core::Response; use jsonrpc_pubsub::{PubSubHandler, Session}; + use solana_budget_api; + use solana_budget_api::budget_transaction::BudgetTransaction; use solana_runtime::bank::{self, Bank}; - use solana_sdk::budget_program; - use solana_sdk::budget_transaction::BudgetTransaction; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; @@ -275,7 +275,7 @@ mod tests { let witness = Keypair::new(); let contract_funds = Keypair::new(); let contract_state = Keypair::new(); - let budget_program_id = budget_program::id(); + let budget_program_id = solana_budget_api::id(); let executable = false; // TODO let bank = Bank::new(&genesis_block); let arc_bank = Arc::new(bank); diff --git a/core/src/rpc_subscriptions.rs b/core/src/rpc_subscriptions.rs index 542a7570d..730e4436f 100644 --- a/core/src/rpc_subscriptions.rs +++ b/core/src/rpc_subscriptions.rs @@ -145,7 +145,7 @@ impl RpcSubscriptions { mod tests { use super::*; use jsonrpc_pubsub::typed::Subscriber; - use solana_sdk::budget_program; + use solana_budget_api; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_transaction::SystemTransaction; @@ -163,7 +163,7 @@ mod tests { blockhash, 1, 16, - budget_program::id(), + solana_budget_api::id(), 0, ); bank.process_transaction(&tx).unwrap(); diff --git a/core/src/sigverify.rs b/core/src/sigverify.rs index 7faf6eabb..4a78ca703 100644 --- a/core/src/sigverify.rs +++ b/core/src/sigverify.rs @@ -335,7 +335,7 @@ mod tests { use crate::sigverify; use crate::test_tx::test_tx; use bincode::{deserialize, serialize}; - use solana_sdk::budget_program; + use solana_budget_api; use solana_sdk::hash::Hash; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; @@ -501,7 +501,7 @@ mod tests { let system_instruction = SystemInstruction::Move { tokens }; - let program_ids = vec![system_program::id(), budget_program::id()]; + let program_ids = vec![system_program::id(), solana_budget_api::id()]; let instructions = vec![Instruction::new(0, &system_instruction, vec![0, 1])]; diff --git a/programs/native/budget/Cargo.toml b/programs/native/budget/Cargo.toml index 1b1306351..78d03589d 100644 --- a/programs/native/budget/Cargo.toml +++ b/programs/native/budget/Cargo.toml @@ -14,6 +14,7 @@ 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.12.0" } solana-logger = { path = "../../../logger", version = "0.12.0" } solana-sdk = { path = "../../../sdk", version = "0.12.0" } diff --git a/programs/native/budget/src/budget_program.rs b/programs/native/budget/src/budget_program.rs index 08e3ef288..76bc6d160 100644 --- a/programs/native/budget/src/budget_program.rs +++ b/programs/native/budget/src/budget_program.rs @@ -3,10 +3,10 @@ use bincode::{self, deserialize, serialize_into, serialized_size}; use chrono::prelude::{DateTime, Utc}; use log::*; use serde_derive::{Deserialize, Serialize}; +use solana_budget_api::budget_expr::BudgetExpr; +use solana_budget_api::budget_instruction::Instruction; +use solana_budget_api::payment_plan::Witness; 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)] @@ -115,22 +115,6 @@ pub fn process_instruction( } } -// 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; - if program.is_pending() { - 0 - } else { - account.tokens - } - } else { - account.tokens - } -} -*/ - impl BudgetProgram { fn is_pending(&self) -> bool { self.pending_budget != None @@ -240,9 +224,9 @@ impl BudgetProgram { mod test { use super::*; use bincode::serialize; + use solana_budget_api::budget_transaction::BudgetTransaction; + use solana_budget_api::id; use solana_sdk::account::Account; - use solana_sdk::budget_program::*; - use solana_sdk::budget_transaction::BudgetTransaction; use solana_sdk::hash::Hash; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::transaction::{Instruction, Transaction}; diff --git a/programs/native/budget_api/Cargo.toml b/programs/native/budget_api/Cargo.toml new file mode 100644 index 000000000..7eced57b1 --- /dev/null +++ b/programs/native/budget_api/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "solana-budget-api" +version = "0.12.0" +description = "Solana Budget program API" +authors = ["Solana Maintainers "] +repository = "https://github.com/solana-labs/solana" +license = "Apache-2.0" +homepage = "https://solana.com/" +edition = "2018" + +[dependencies] +bincode = "1.1.2" +chrono = { version = "0.4.0", features = ["serde"] } +serde = "1.0.89" +serde_derive = "1.0.89" +solana-sdk = { path = "../../../sdk", version = "0.12.0" } + +[lib] +name = "solana_budget_api" +crate-type = ["lib"] diff --git a/sdk/src/budget_expr.rs b/programs/native/budget_api/src/budget_expr.rs similarity index 98% rename from sdk/src/budget_expr.rs rename to programs/native/budget_api/src/budget_expr.rs index a97649565..b14d827d2 100644 --- a/sdk/src/budget_expr.rs +++ b/programs/native/budget_api/src/budget_expr.rs @@ -4,8 +4,9 @@ //! `Payment`, the payment is executed. use crate::payment_plan::{Payment, Witness}; -use crate::pubkey::Pubkey; use chrono::prelude::*; +use serde_derive::{Deserialize, Serialize}; +use solana_sdk::pubkey::Pubkey; use std::mem; /// A data type representing a `Witness` that the payment plan is waiting on. @@ -152,7 +153,7 @@ impl BudgetExpr { #[cfg(test)] mod tests { use super::*; - use crate::signature::{Keypair, KeypairUtil}; + use solana_sdk::signature::{Keypair, KeypairUtil}; #[test] fn test_signature_satisfied() { diff --git a/sdk/src/budget_instruction.rs b/programs/native/budget_api/src/budget_instruction.rs similarity index 77% rename from sdk/src/budget_instruction.rs rename to programs/native/budget_api/src/budget_instruction.rs index accec702e..c66fd709f 100644 --- a/sdk/src/budget_instruction.rs +++ b/programs/native/budget_api/src/budget_instruction.rs @@ -1,8 +1,9 @@ use crate::budget_expr::BudgetExpr; -use crate::budget_program; -use crate::pubkey::Pubkey; -use crate::transaction_builder::BuilderInstruction; +use crate::id; use chrono::prelude::{DateTime, Utc}; +use serde_derive::{Deserialize, Serialize}; +use solana_sdk::pubkey::Pubkey; +use solana_sdk::transaction_builder::BuilderInstruction; /// A smart contract. #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] @@ -28,10 +29,6 @@ pub enum Instruction { impl Instruction { pub fn new_budget(contract: Pubkey, expr: BudgetExpr) -> BuilderInstruction { - BuilderInstruction::new( - budget_program::id(), - &Instruction::NewBudget(expr), - vec![(contract, false)], - ) + BuilderInstruction::new(id(), &Instruction::NewBudget(expr), vec![(contract, false)]) } } diff --git a/sdk/src/budget_program.rs b/programs/native/budget_api/src/budget_program.rs similarity index 100% rename from sdk/src/budget_program.rs rename to programs/native/budget_api/src/budget_program.rs diff --git a/sdk/src/budget_transaction.rs b/programs/native/budget_api/src/budget_transaction.rs similarity index 94% rename from sdk/src/budget_transaction.rs rename to programs/native/budget_api/src/budget_transaction.rs index 5961ca768..c0e7a3a69 100644 --- a/sdk/src/budget_transaction.rs +++ b/programs/native/budget_api/src/budget_transaction.rs @@ -2,15 +2,15 @@ use crate::budget_expr::{BudgetExpr, Condition}; use crate::budget_instruction::Instruction; -use crate::budget_program; -use crate::hash::Hash; -use crate::pubkey::Pubkey; -use crate::signature::{Keypair, KeypairUtil}; -use crate::system_instruction::SystemInstruction; -use crate::transaction::Transaction; -use crate::transaction_builder::TransactionBuilder; +use crate::id; use bincode::deserialize; use chrono::prelude::*; +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::transaction::Transaction; +use solana_sdk::transaction_builder::TransactionBuilder; pub struct BudgetTransaction {} @@ -55,7 +55,7 @@ impl BudgetTransaction { Transaction::new( from_keypair, &[contract, to], - budget_program::id(), + id(), &instruction, recent_blockhash, 0, @@ -74,14 +74,7 @@ impl BudgetTransaction { if from_keypair.pubkey() != to { keys.push(to); } - Transaction::new( - from_keypair, - &keys, - budget_program::id(), - &instruction, - recent_blockhash, - 0, - ) + Transaction::new(from_keypair, &keys, id(), &instruction, recent_blockhash, 0) } /// Create and sign a postdated Transaction. Used for unit-testing. @@ -116,7 +109,7 @@ impl BudgetTransaction { Transaction::new( from_keypair, &[contract], - budget_program::id(), + id(), &instruction, recent_blockhash, 0, @@ -153,7 +146,7 @@ impl BudgetTransaction { Transaction::new( from_keypair, &[contract], - budget_program::id(), + id(), &instruction, recent_blockhash, 0, diff --git a/programs/native/budget_api/src/lib.rs b/programs/native/budget_api/src/lib.rs new file mode 100644 index 000000000..a4e138cbe --- /dev/null +++ b/programs/native/budget_api/src/lib.rs @@ -0,0 +1,19 @@ +pub mod budget_expr; +pub mod budget_instruction; +pub mod budget_transaction; +pub mod payment_plan; + +use solana_sdk::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/programs/native/budget_api/src/payment_plan.rs b/programs/native/budget_api/src/payment_plan.rs new file mode 100644 index 000000000..2ae29b555 --- /dev/null +++ b/programs/native/budget_api/src/payment_plan.rs @@ -0,0 +1,28 @@ +//! The `plan` module provides a domain-specific language for payment plans. Users create BudgetExpr objects that +//! are given to an interpreter. The interpreter listens for `Witness` transactions, +//! which it uses to reduce the payment plan. When the plan is reduced to a +//! `Payment`, the payment is executed. + +use chrono::prelude::*; +use serde_derive::{Deserialize, Serialize}; +use solana_sdk::pubkey::Pubkey; + +/// The types of events a payment plan can process. +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +pub enum Witness { + /// The current time. + Timestamp(DateTime), + + /// A signature from Pubkey. + Signature, +} + +/// Some amount of tokens that should be sent to the `to` `Pubkey`. +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +pub struct Payment { + /// Amount to be paid. + pub tokens: u64, + + /// The `Pubkey` that `tokens` should be paid to. + pub to: Pubkey, +} diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 8e1e14275..db7164d88 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -19,6 +19,7 @@ rand = "0.6.5" serde = "1.0.88" serde_derive = "1.0.88" serde_json = "1.0.38" +solana-budget-api = { path = "../programs/native/budget_api", version = "0.12.0" } solana-logger = { path = "../logger", version = "0.12.0" } solana-metrics = { path = "../metrics", version = "0.12.0" } solana-sdk = { path = "../sdk", version = "0.12.0" } diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index e2082cd24..e8e7ecd09 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -10,10 +10,10 @@ use crate::status_cache::StatusCache; use bincode::serialize; use hashbrown::HashMap; use log::*; +use solana_budget_api; use solana_metrics::counter::Counter; use solana_sdk::account::Account; use solana_sdk::bpf_loader; -use solana_sdk::budget_program; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::hash::{extend_and_hash, Hash}; use solana_sdk::native_loader; @@ -293,7 +293,7 @@ impl Bank { self.add_native_program("solana_vote_program", &vote_program::id()); self.add_native_program("solana_storage_program", &storage_program::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", &solana_budget_api::id()); self.add_native_program("solana_token_program", &token_program::id()); } @@ -647,12 +647,6 @@ impl Bank { } pub fn read_balance(account: &Account) -> u64 { - // TODO: Re-instate budget_program special case? - /* - if budget_program::check_id(&account.owner) { - return budget_program::get_balance(account); - } - */ account.tokens } /// Each program would need to be able to introspect its own state @@ -1291,7 +1285,7 @@ mod tests { assert_eq!(system_program::id(), system); assert_eq!(native_loader::id(), native); assert_eq!(bpf_loader::id(), bpf); - assert_eq!(budget_program::id(), budget); + assert_eq!(solana_budget_api::id(), budget); assert_eq!(storage_program::id(), storage); assert_eq!(token_program::id(), token); assert_eq!(vote_program::id(), vote); @@ -1304,7 +1298,7 @@ mod tests { system_program::id(), native_loader::id(), bpf_loader::id(), - budget_program::id(), + solana_budget_api::id(), storage_program::id(), token_program::id(), vote_program::id(), diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 27c3a7452..5fea1bfa3 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -1,9 +1,5 @@ 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 genesis_block; pub mod hash; pub mod loader_instruction; @@ -11,7 +7,6 @@ pub mod loader_transaction; pub mod native_loader; pub mod native_program; pub mod packet; -pub mod payment_plan; pub mod pubkey; pub mod shortvec; pub mod signature; diff --git a/wallet/Cargo.toml b/wallet/Cargo.toml index 6e3634e08..f5869f89c 100644 --- a/wallet/Cargo.toml +++ b/wallet/Cargo.toml @@ -17,6 +17,7 @@ dirs = "1.0.5" log = "0.4.2" serde_json = "1.0.39" solana = { path = "../core", version = "0.12.0" } +solana-budget-api = { path = "../programs/native/budget_api", version = "0.12.0" } solana-drone = { path = "../drone", version = "0.12.0" } solana-logger = { path = "../logger", version = "0.12.0" } solana-sdk = { path = "../sdk", version = "0.12.0" } diff --git a/wallet/src/wallet.rs b/wallet/src/wallet.rs index ce8f72a19..cb2e8c62f 100644 --- a/wallet/src/wallet.rs +++ b/wallet/src/wallet.rs @@ -12,12 +12,12 @@ use solana::rpc_request::RpcClient; use solana::rpc_request::{get_rpc_request_str, RpcRequest}; use solana::rpc_service::RPC_PORT; use solana::rpc_status::RpcSignatureStatus; +use solana_budget_api; +use solana_budget_api::budget_transaction::BudgetTransaction; #[cfg(not(test))] use solana_drone::drone::request_airdrop_transaction; use solana_drone::drone::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::loader_transaction::LoaderTransaction; use solana_sdk::pubkey::Pubkey; @@ -483,7 +483,7 @@ fn process_pay( let contract_funds = Keypair::new(); let contract_state = Keypair::new(); - let budget_program_id = budget_program::id(); + let budget_program_id = solana_budget_api::id(); // Create account for contract funds let mut tx = SystemTransaction::new_program_account( @@ -540,7 +540,7 @@ fn process_pay( let contract_funds = Keypair::new(); let contract_state = Keypair::new(); - let budget_program_id = budget_program::id(); + let budget_program_id = solana_budget_api::id(); // Create account for contract funds let mut tx = SystemTransaction::new_program_account(