From 694add9919c7ac419afdf4c26008de6870330377 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 26 Sep 2018 09:51:51 -0600 Subject: [PATCH] Move budget-specific and system-specific tx constructors into traits These functions pull in budget-specific and system-specific dependencies that aren't needed by the runtime. --- src/bank.rs | 12 +- src/banking_stage.rs | 12 +- src/bin/bench-tps.rs | 6 +- src/budget_program.rs | 2 +- src/drone.rs | 4 +- src/entry.rs | 8 +- src/ledger.rs | 2 +- src/mint.rs | 2 +- src/rpc.rs | 2 +- src/system_program.rs | 4 +- src/thin_client.rs | 8 +- src/transaction.rs | 516 ++++++++++++++++++++++++------------------ src/tvu.rs | 2 +- src/vote_stage.rs | 4 +- src/wallet.rs | 4 +- 15 files changed, 334 insertions(+), 254 deletions(-) diff --git a/src/bank.rs b/src/bank.rs index abd1efefe5..a952e100ee 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -26,7 +26,7 @@ use storage_program::StorageProgram; use system_program::SystemProgram; use tictactoe_program::TicTacToeProgram; use timing::{duration_as_us, timestamp}; -use transaction::Transaction; +use transaction::{SystemTransaction, Transaction}; use window::WINDOW_SIZE; /// An Account with userdata that is stored on chain @@ -673,7 +673,7 @@ impl Bank { to: Pubkey, last_id: Hash, ) -> Result { - let tx = Transaction::new(keypair, to, n, last_id); + let tx = Transaction::system_new(keypair, to, n, last_id); let signature = tx.signature; self.process_transaction(&tx).map(|_| signature) } @@ -798,7 +798,7 @@ mod tests { let dest = Keypair::new(); // source with 0 contract context - let tx = Transaction::new(&mint.keypair(), dest.pubkey(), 2, mint.last_id()); + let tx = Transaction::system_new(&mint.keypair(), dest.pubkey(), 2, mint.last_id()); let signature = tx.signature; assert!(!bank.has_signature(&signature)); let res = bank.process_transaction(&tx); @@ -930,8 +930,8 @@ mod tests { let mint = Mint::new(2); let bank = Bank::new(&mint); let keypair = Keypair::new(); - let tx0 = Transaction::new(&mint.keypair(), keypair.pubkey(), 2, mint.last_id()); - let tx1 = Transaction::new(&keypair, mint.pubkey(), 1, mint.last_id()); + let tx0 = Transaction::system_new(&mint.keypair(), keypair.pubkey(), 2, mint.last_id()); + let tx1 = Transaction::system_new(&keypair, mint.pubkey(), 1, mint.last_id()); let txs = vec![tx0, tx1]; let results = bank.process_transactions(&txs); assert!(results[1].is_err()); @@ -946,7 +946,7 @@ mod tests { let bank = Bank::new(&mint); let keypair = Keypair::new(); let entry = next_entry(&mint.last_id(), 1, vec![]); - let tx = Transaction::new(&mint.keypair(), keypair.pubkey(), 1, entry.id); + let tx = Transaction::system_new(&mint.keypair(), keypair.pubkey(), 1, entry.id); // First, ensure the TX is rejected because of the unregistered last ID assert_eq!( diff --git a/src/banking_stage.rs b/src/banking_stage.rs index b6a2a20dc6..5312a2de62 100644 --- a/src/banking_stage.rs +++ b/src/banking_stage.rs @@ -248,7 +248,7 @@ mod tests { use packet::{to_packets, PacketRecycler}; use signature::{Keypair, KeypairUtil}; use std::thread::sleep; - use transaction::Transaction; + use transaction::{SystemTransaction, Transaction}; #[test] fn test_banking_stage_shutdown() { @@ -304,14 +304,14 @@ mod tests { // good tx let keypair = mint.keypair(); - let tx = Transaction::new(&keypair, keypair.pubkey(), 1, start_hash); + let tx = Transaction::system_new(&keypair, keypair.pubkey(), 1, start_hash); // good tx, but no verify - let tx_no_ver = Transaction::new(&keypair, keypair.pubkey(), 1, start_hash); + let tx_no_ver = Transaction::system_new(&keypair, keypair.pubkey(), 1, start_hash); // bad tx, AccountNotFound let keypair = Keypair::new(); - let tx_anf = Transaction::new(&keypair, keypair.pubkey(), 1, start_hash); + let tx_anf = Transaction::system_new(&keypair, keypair.pubkey(), 1, start_hash); // send 'em over let recycler = PacketRecycler::default(); @@ -350,7 +350,7 @@ mod tests { // Process a batch that includes a transaction that receives two tokens. let alice = Keypair::new(); - let tx = Transaction::new(&mint.keypair(), alice.pubkey(), 2, mint.last_id()); + let tx = Transaction::system_new(&mint.keypair(), alice.pubkey(), 2, mint.last_id()); let packets = to_packets(&recycler, &[tx]); verified_sender @@ -358,7 +358,7 @@ mod tests { .unwrap(); // Process a second batch that spends one of those tokens. - let tx = Transaction::new(&alice, mint.pubkey(), 1, mint.last_id()); + let tx = Transaction::system_new(&alice, mint.pubkey(), 1, mint.last_id()); let packets = to_packets(&recycler, &[tx]); verified_sender .send(vec![(packets[0].clone(), vec![1u8])]) diff --git a/src/bin/bench-tps.rs b/src/bin/bench-tps.rs index 770ba71a32..c34bd614c7 100644 --- a/src/bin/bench-tps.rs +++ b/src/bin/bench-tps.rs @@ -21,7 +21,7 @@ use solana::service::Service; use solana::signature::{read_keypair, GenKeys, Keypair, KeypairUtil}; use solana::thin_client::{poll_gossip_for_leader, ThinClient}; use solana::timing::{duration_as_ms, duration_as_s}; -use solana::transaction::Transaction; +use solana::transaction::{SystemTransaction, Transaction}; use solana::wallet::request_airdrop; use solana::window::default_window; use std::collections::VecDeque; @@ -187,9 +187,9 @@ fn generate_txs( .par_iter() .map(|keypair| { if !reclaim { - Transaction::new(&id, keypair.pubkey(), 1, *last_id) + Transaction::system_new(&id, keypair.pubkey(), 1, *last_id) } else { - Transaction::new(keypair, id.pubkey(), 1, *last_id) + Transaction::system_new(keypair, id.pubkey(), 1, *last_id) } }).collect(); diff --git a/src/budget_program.rs b/src/budget_program.rs index af3ef2d6de..12f4111c87 100644 --- a/src/budget_program.rs +++ b/src/budget_program.rs @@ -271,7 +271,7 @@ mod test { use chrono::prelude::{DateTime, NaiveDate, Utc}; use hash::Hash; use signature::{GenKeys, Keypair, KeypairUtil, Pubkey}; - use transaction::Transaction; + use transaction::{BudgetTransaction, Transaction}; #[test] fn test_serializer() { let mut a = Account::new(0, 512, BudgetState::id()); diff --git a/src/drone.rs b/src/drone.rs index 5935fcaef5..40693c240e 100644 --- a/src/drone.rs +++ b/src/drone.rs @@ -22,7 +22,7 @@ use tokio; use tokio::net::TcpListener; use tokio::prelude::*; use tokio_codec::{BytesCodec, Decoder}; -use transaction::Transaction; +use transaction::{SystemTransaction, Transaction}; pub const TIME_SLICE: u64 = 60; pub const REQUEST_CAP: u64 = 500_000_000; @@ -127,7 +127,7 @@ impl Drone { airdrop_request_amount, client_pubkey ); request_amount = airdrop_request_amount; - Transaction::new( + Transaction::system_new( &self.mint_keypair, client_pubkey, airdrop_request_amount as i64, diff --git a/src/entry.rs b/src/entry.rs index 5b295e48d9..9639ebecb6 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -230,7 +230,7 @@ mod tests { use entry::Entry; use hash::hash; use signature::{Keypair, KeypairUtil}; - use transaction::Transaction; + use transaction::{BudgetTransaction, SystemTransaction, Transaction}; #[test] fn test_entry_verify() { @@ -248,8 +248,8 @@ mod tests { // First, verify entries let keypair = Keypair::new(); - let tx0 = Transaction::new(&keypair, keypair.pubkey(), 0, zero); - let tx1 = Transaction::new(&keypair, keypair.pubkey(), 1, zero); + let tx0 = Transaction::system_new(&keypair, keypair.pubkey(), 0, zero); + let tx1 = Transaction::system_new(&keypair, keypair.pubkey(), 1, zero); let mut e0 = Entry::new(&zero, 0, vec![tx0.clone(), tx1.clone()]); assert!(e0.verify(&zero)); @@ -312,7 +312,7 @@ mod tests { fn test_next_entry_panic() { let zero = Hash::default(); let keypair = Keypair::new(); - let tx = Transaction::new(&keypair, keypair.pubkey(), 0, zero); + let tx = Transaction::system_new(&keypair, keypair.pubkey(), 0, zero); next_entry(&zero, 0, vec![tx]); } } diff --git a/src/ledger.rs b/src/ledger.rs index 00c637699b..4cf3a028b3 100644 --- a/src/ledger.rs +++ b/src/ledger.rs @@ -584,7 +584,7 @@ mod tests { use signature::{Keypair, KeypairUtil}; use std; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - use transaction::Transaction; + use transaction::{BudgetTransaction, Transaction}; #[test] fn test_verify_slice() { diff --git a/src/mint.rs b/src/mint.rs index e7545142cd..203f1490a6 100644 --- a/src/mint.rs +++ b/src/mint.rs @@ -4,7 +4,7 @@ use entry::Entry; use hash::{hash, Hash}; use ring::rand::SystemRandom; use signature::{Keypair, KeypairUtil, Pubkey}; -use transaction::Transaction; +use transaction::{SystemTransaction, Transaction}; use untrusted::Input; #[derive(Serialize, Deserialize, Debug)] diff --git a/src/rpc.rs b/src/rpc.rs index 1d24eee9c4..8680c362db 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -241,7 +241,7 @@ mod tests { use signature::{Keypair, KeypairUtil}; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::sync::Arc; - use transaction::Transaction; + use transaction::{SystemTransaction, Transaction}; #[test] fn test_rpc_request() { diff --git a/src/system_program.rs b/src/system_program.rs index 1f0ed0a0b9..cfbf41dfbd 100644 --- a/src/system_program.rs +++ b/src/system_program.rs @@ -106,7 +106,7 @@ mod test { use std::sync::RwLock; use std::thread; use system_program::SystemProgram; - use transaction::Transaction; + use transaction::{SystemTransaction, Transaction}; #[test] fn test_create_noop() { @@ -336,7 +336,7 @@ mod test { let to = Keypair::new(); let mut accounts = vec![Account::default(), Account::default()]; accounts[0].tokens = 1; - let tx = Transaction::new(&from, to.pubkey(), 1, Hash::default()); + let tx = Transaction::system_new(&from, to.pubkey(), 1, Hash::default()); let hash = RwLock::new(HashMap::new()); SystemProgram::process_transaction(&tx, &mut accounts, &hash); assert_eq!(accounts[0].tokens, 0); diff --git a/src/thin_client.rs b/src/thin_client.rs index a758a8eda0..aa6f0f6492 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -22,7 +22,7 @@ use std::thread::sleep; use std::time::Duration; use std::time::Instant; use timing; -use transaction::Transaction; +use transaction::{SystemTransaction, Transaction}; use influx_db_client as influxdb; use metrics; @@ -154,7 +154,7 @@ impl ThinClient { last_id: &Hash, ) -> io::Result { let now = Instant::now(); - let tx = Transaction::new(keypair, to, n, *last_id); + let tx = Transaction::system_new(keypair, to, n, *last_id); let result = self.transfer_signed(&tx); metrics::submit( influxdb::Point::new("thinclient") @@ -530,13 +530,13 @@ mod tests { ); let last_id = client.get_last_id(); - let tx = Transaction::new(&alice.keypair(), bob_pubkey, 500, last_id); + let tx = Transaction::system_new(&alice.keypair(), bob_pubkey, 500, last_id); let _sig = client.transfer_signed(&tx).unwrap(); let last_id = client.get_last_id(); - let mut tr2 = Transaction::new(&alice.keypair(), bob_pubkey, 501, last_id); + let mut tr2 = Transaction::system_new(&alice.keypair(), bob_pubkey, 501, last_id); let mut instruction2 = deserialize(&tr2.userdata).unwrap(); if let SystemProgram::Move { ref mut tokens } = instruction2 { *tokens = 502; diff --git a/src/transaction.rs b/src/transaction.rs index 3c9451a9e1..1284debf4f 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -71,225 +71,7 @@ impl Transaction { tx.sign(from_keypair); tx } - /// Create and sign a new Transaction. Used for unit-testing. - pub fn budget_new_taxed( - from_keypair: &Keypair, - to: Pubkey, - tokens: i64, - fee: i64, - last_id: Hash, - ) -> Self { - let payment = Payment { - tokens: tokens - fee, - to, - }; - let budget = Budget::Pay(payment); - let instruction = Instruction::NewContract(Contract { budget, tokens }); - let userdata = serialize(&instruction).unwrap(); - Self::new_with_userdata( - from_keypair, - &[to], - BudgetState::id(), - userdata, - last_id, - fee, - ) - } - /// Create and sign a new Transaction. Used for unit-testing. - pub fn budget_new(from_keypair: &Keypair, to: Pubkey, tokens: i64, last_id: Hash) -> Self { - Self::budget_new_taxed(from_keypair, to, tokens, 0, last_id) - } - - /// Create and sign a new Witness Timestamp. Used for unit-testing. - pub fn budget_new_timestamp( - from_keypair: &Keypair, - contract: Pubkey, - to: Pubkey, - dt: DateTime, - last_id: Hash, - ) -> Self { - let instruction = Instruction::ApplyTimestamp(dt); - let userdata = serialize(&instruction).unwrap(); - Self::new_with_userdata( - from_keypair, - &[contract, to], - BudgetState::id(), - userdata, - last_id, - 0, - ) - } - - /// Create and sign a new Witness Signature. Used for unit-testing. - pub fn budget_new_signature( - from_keypair: &Keypair, - contract: Pubkey, - to: Pubkey, - last_id: Hash, - ) -> Self { - let instruction = Instruction::ApplySignature; - let userdata = serialize(&instruction).unwrap(); - Self::new_with_userdata( - from_keypair, - &[contract, to], - BudgetState::id(), - userdata, - last_id, - 0, - ) - } - - pub fn budget_new_vote(from_keypair: &Keypair, vote: Vote, last_id: Hash, fee: i64) -> Self { - let instruction = Instruction::NewVote(vote); - let userdata = serialize(&instruction).expect("serialize instruction"); - Self::new_with_userdata(from_keypair, &[], BudgetState::id(), userdata, last_id, fee) - } - - /// Create and sign a postdated Transaction. Used for unit-testing. - pub fn budget_new_on_date( - from_keypair: &Keypair, - to: Pubkey, - contract: Pubkey, - dt: DateTime, - dt_pubkey: Pubkey, - cancelable: Option, - tokens: i64, - last_id: Hash, - ) -> Self { - let budget = if let Some(from) = cancelable { - Budget::Or( - (Condition::Timestamp(dt, dt_pubkey), Payment { tokens, to }), - (Condition::Signature(from), Payment { tokens, to: from }), - ) - } else { - Budget::After(Condition::Timestamp(dt, dt_pubkey), Payment { tokens, to }) - }; - let instruction = Instruction::NewContract(Contract { budget, tokens }); - let userdata = serialize(&instruction).expect("serialize instruction"); - Self::new_with_userdata( - from_keypair, - &[contract], - BudgetState::id(), - userdata, - last_id, - 0, - ) - } - /// Create and sign a multisig Transaction. - pub fn budget_new_when_signed( - from_keypair: &Keypair, - to: Pubkey, - contract: Pubkey, - witness: Pubkey, - cancelable: Option, - tokens: i64, - last_id: Hash, - ) -> Self { - let budget = if let Some(from) = cancelable { - Budget::Or( - (Condition::Signature(witness), Payment { tokens, to }), - (Condition::Signature(from), Payment { tokens, to: from }), - ) - } else { - Budget::After(Condition::Signature(witness), Payment { tokens, to }) - }; - let instruction = Instruction::NewContract(Contract { budget, tokens }); - let userdata = serialize(&instruction).expect("serialize instruction"); - Self::new_with_userdata( - from_keypair, - &[contract], - BudgetState::id(), - userdata, - last_id, - 0, - ) - } - /// Create and sign new SystemProgram::CreateAccount transaction - pub fn system_create( - from_keypair: &Keypair, - to: Pubkey, - last_id: Hash, - tokens: i64, - space: u64, - program_id: Pubkey, - fee: i64, - ) -> Self { - let create = SystemProgram::CreateAccount { - tokens, //TODO, the tokens to allocate might need to be higher then 0 in the future - space, - program_id, - }; - Transaction::new_with_userdata( - from_keypair, - &[to], - SystemProgram::id(), - serialize(&create).unwrap(), - last_id, - fee, - ) - } - /// Create and sign new SystemProgram::CreateAccount transaction - pub fn system_assign( - from_keypair: &Keypair, - last_id: Hash, - program_id: Pubkey, - fee: i64, - ) -> Self { - let create = SystemProgram::Assign { program_id }; - Transaction::new_with_userdata( - from_keypair, - &[], - SystemProgram::id(), - serialize(&create).unwrap(), - last_id, - fee, - ) - } - /// Create and sign new SystemProgram::CreateAccount transaction with some defaults - pub fn system_new(from_keypair: &Keypair, to: Pubkey, tokens: i64, last_id: Hash) -> Self { - Transaction::system_create(from_keypair, to, last_id, tokens, 0, Pubkey::default(), 0) - } - /// Create and sign new SystemProgram::Move transaction - pub fn system_move( - from_keypair: &Keypair, - to: Pubkey, - tokens: i64, - last_id: Hash, - fee: i64, - ) -> Self { - let create = SystemProgram::Move { tokens }; - Transaction::new_with_userdata( - from_keypair, - &[to], - SystemProgram::id(), - serialize(&create).unwrap(), - last_id, - fee, - ) - } - /// Create and sign new SystemProgram::Load transaction - pub fn system_load( - from_keypair: &Keypair, - last_id: Hash, - fee: i64, - program_id: Pubkey, - name: String, - ) -> Self { - let load = SystemProgram::Load { program_id, name }; - Transaction::new_with_userdata( - from_keypair, - &[], - SystemProgram::id(), - serialize(&load).unwrap(), - last_id, - fee, - ) - } - /// Create and sign new SystemProgram::Move transaction - pub fn new(from_keypair: &Keypair, to: Pubkey, tokens: i64, last_id: Hash) -> Self { - Transaction::system_move(from_keypair, to, tokens, last_id, 0) - } /// Get the transaction data to sign. fn get_sign_data(&self) -> Vec { let mut data = serialize(&(&self.keys)).expect("serialize keys"); @@ -354,6 +136,304 @@ impl Transaction { } } +pub trait BudgetTransaction { + fn budget_new_taxed( + from_keypair: &Keypair, + to: Pubkey, + tokens: i64, + fee: i64, + last_id: Hash, + ) -> Self; + + fn budget_new(from_keypair: &Keypair, to: Pubkey, tokens: i64, last_id: Hash) -> Self; + + fn budget_new_timestamp( + from_keypair: &Keypair, + contract: Pubkey, + to: Pubkey, + dt: DateTime, + last_id: Hash, + ) -> Self; + + fn budget_new_signature( + from_keypair: &Keypair, + contract: Pubkey, + to: Pubkey, + last_id: Hash, + ) -> Self; + + fn budget_new_vote(from_keypair: &Keypair, vote: Vote, last_id: Hash, fee: i64) -> Self; + + fn budget_new_on_date( + from_keypair: &Keypair, + to: Pubkey, + contract: Pubkey, + dt: DateTime, + dt_pubkey: Pubkey, + cancelable: Option, + tokens: i64, + last_id: Hash, + ) -> Self; + + fn budget_new_when_signed( + from_keypair: &Keypair, + to: Pubkey, + contract: Pubkey, + witness: Pubkey, + cancelable: Option, + tokens: i64, + last_id: Hash, + ) -> Self; +} + +impl BudgetTransaction for Transaction { + /// Create and sign a new Transaction. Used for unit-testing. + fn budget_new_taxed( + from_keypair: &Keypair, + to: Pubkey, + tokens: i64, + fee: i64, + last_id: Hash, + ) -> Self { + let payment = Payment { + tokens: tokens - fee, + to, + }; + let budget = Budget::Pay(payment); + let instruction = Instruction::NewContract(Contract { budget, tokens }); + let userdata = serialize(&instruction).unwrap(); + Self::new_with_userdata( + from_keypair, + &[to], + BudgetState::id(), + userdata, + last_id, + fee, + ) + } + + /// Create and sign a new Transaction. Used for unit-testing. + fn budget_new(from_keypair: &Keypair, to: Pubkey, tokens: i64, last_id: Hash) -> Self { + Self::budget_new_taxed(from_keypair, to, tokens, 0, last_id) + } + + /// Create and sign a new Witness Timestamp. Used for unit-testing. + fn budget_new_timestamp( + from_keypair: &Keypair, + contract: Pubkey, + to: Pubkey, + dt: DateTime, + last_id: Hash, + ) -> Self { + let instruction = Instruction::ApplyTimestamp(dt); + let userdata = serialize(&instruction).unwrap(); + Self::new_with_userdata( + from_keypair, + &[contract, to], + BudgetState::id(), + userdata, + last_id, + 0, + ) + } + + /// Create and sign a new Witness Signature. Used for unit-testing. + fn budget_new_signature( + from_keypair: &Keypair, + contract: Pubkey, + to: Pubkey, + last_id: Hash, + ) -> Self { + let instruction = Instruction::ApplySignature; + let userdata = serialize(&instruction).unwrap(); + Self::new_with_userdata( + from_keypair, + &[contract, to], + BudgetState::id(), + userdata, + last_id, + 0, + ) + } + + fn budget_new_vote(from_keypair: &Keypair, vote: Vote, last_id: Hash, fee: i64) -> Self { + let instruction = Instruction::NewVote(vote); + let userdata = serialize(&instruction).expect("serialize instruction"); + Self::new_with_userdata(from_keypair, &[], BudgetState::id(), userdata, last_id, fee) + } + + /// Create and sign a postdated Transaction. Used for unit-testing. + fn budget_new_on_date( + from_keypair: &Keypair, + to: Pubkey, + contract: Pubkey, + dt: DateTime, + dt_pubkey: Pubkey, + cancelable: Option, + tokens: i64, + last_id: Hash, + ) -> Self { + let budget = if let Some(from) = cancelable { + Budget::Or( + (Condition::Timestamp(dt, dt_pubkey), Payment { tokens, to }), + (Condition::Signature(from), Payment { tokens, to: from }), + ) + } else { + Budget::After(Condition::Timestamp(dt, dt_pubkey), Payment { tokens, to }) + }; + let instruction = Instruction::NewContract(Contract { budget, tokens }); + let userdata = serialize(&instruction).expect("serialize instruction"); + Self::new_with_userdata( + from_keypair, + &[contract], + BudgetState::id(), + userdata, + last_id, + 0, + ) + } + /// Create and sign a multisig Transaction. + fn budget_new_when_signed( + from_keypair: &Keypair, + to: Pubkey, + contract: Pubkey, + witness: Pubkey, + cancelable: Option, + tokens: i64, + last_id: Hash, + ) -> Self { + let budget = if let Some(from) = cancelable { + Budget::Or( + (Condition::Signature(witness), Payment { tokens, to }), + (Condition::Signature(from), Payment { tokens, to: from }), + ) + } else { + Budget::After(Condition::Signature(witness), Payment { tokens, to }) + }; + let instruction = Instruction::NewContract(Contract { budget, tokens }); + let userdata = serialize(&instruction).expect("serialize instruction"); + Self::new_with_userdata( + from_keypair, + &[contract], + BudgetState::id(), + userdata, + last_id, + 0, + ) + } +} + +pub trait SystemTransaction { + fn system_create( + from_keypair: &Keypair, + to: Pubkey, + last_id: Hash, + tokens: i64, + space: u64, + program_id: Pubkey, + fee: i64, + ) -> Self; + + fn system_assign(from_keypair: &Keypair, last_id: Hash, program_id: Pubkey, fee: i64) -> Self; + + fn system_new(from_keypair: &Keypair, to: Pubkey, tokens: i64, last_id: Hash) -> Self; + + fn system_move( + from_keypair: &Keypair, + to: Pubkey, + tokens: i64, + last_id: Hash, + fee: i64, + ) -> Self; + + fn system_load( + from_keypair: &Keypair, + last_id: Hash, + fee: i64, + program_id: Pubkey, + name: String, + ) -> Self; +} + +impl SystemTransaction for Transaction { + /// Create and sign new SystemProgram::CreateAccount transaction + fn system_create( + from_keypair: &Keypair, + to: Pubkey, + last_id: Hash, + tokens: i64, + space: u64, + program_id: Pubkey, + fee: i64, + ) -> Self { + let create = SystemProgram::CreateAccount { + tokens, //TODO, the tokens to allocate might need to be higher then 0 in the future + space, + program_id, + }; + Transaction::new_with_userdata( + from_keypair, + &[to], + SystemProgram::id(), + serialize(&create).unwrap(), + last_id, + fee, + ) + } + /// Create and sign new SystemProgram::CreateAccount transaction + fn system_assign(from_keypair: &Keypair, last_id: Hash, program_id: Pubkey, fee: i64) -> Self { + let create = SystemProgram::Assign { program_id }; + Transaction::new_with_userdata( + from_keypair, + &[], + SystemProgram::id(), + serialize(&create).unwrap(), + last_id, + fee, + ) + } + /// Create and sign new SystemProgram::CreateAccount transaction with some defaults + fn system_new(from_keypair: &Keypair, to: Pubkey, tokens: i64, last_id: Hash) -> Self { + Transaction::system_create(from_keypair, to, last_id, tokens, 0, Pubkey::default(), 0) + } + /// Create and sign new SystemProgram::Move transaction + fn system_move( + from_keypair: &Keypair, + to: Pubkey, + tokens: i64, + last_id: Hash, + fee: i64, + ) -> Self { + let create = SystemProgram::Move { tokens }; + Transaction::new_with_userdata( + from_keypair, + &[to], + SystemProgram::id(), + serialize(&create).unwrap(), + last_id, + fee, + ) + } + /// Create and sign new SystemProgram::Load transaction + fn system_load( + from_keypair: &Keypair, + last_id: Hash, + fee: i64, + program_id: Pubkey, + name: String, + ) -> Self { + let load = SystemProgram::Load { program_id, name }; + Transaction::new_with_userdata( + from_keypair, + &[], + SystemProgram::id(), + serialize(&load).unwrap(), + last_id, + fee, + ) + } +} + pub fn test_tx() -> Transaction { let keypair1 = Keypair::new(); let pubkey1 = keypair1.pubkey(); diff --git a/src/tvu.rs b/src/tvu.rs index 25d3086b75..1637ce828f 100644 --- a/src/tvu.rs +++ b/src/tvu.rs @@ -166,7 +166,7 @@ pub mod tests { use std::sync::{Arc, RwLock}; use std::time::Duration; use streamer; - use transaction::Transaction; + use transaction::{SystemTransaction, Transaction}; use tvu::Tvu; use window::{self, SharedWindow}; diff --git a/src/vote_stage.rs b/src/vote_stage.rs index deda714144..bda99acfe5 100644 --- a/src/vote_stage.rs +++ b/src/vote_stage.rs @@ -16,7 +16,7 @@ use std::sync::atomic::AtomicUsize; use std::sync::{Arc, RwLock}; use streamer::BlobSender; use timing; -use transaction::Transaction; +use transaction::{BudgetTransaction, Transaction}; pub const VOTE_TIMEOUT_MS: u64 = 1000; @@ -177,7 +177,7 @@ pub mod tests { use std::sync::{Arc, RwLock}; use std::thread::sleep; use std::time::Duration; - use transaction::Transaction; + use transaction::{SystemTransaction, Transaction}; #[test] fn test_send_leader_vote() { diff --git a/src/wallet.rs b/src/wallet.rs index 620afbd20c..f7bd8810c4 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -22,7 +22,7 @@ use std::path::Path; use std::thread::sleep; use std::time::Duration; use std::{error, fmt, mem}; -use transaction::Transaction; +use transaction::{BudgetTransaction, SystemTransaction, Transaction}; #[derive(Debug, PartialEq)] pub enum WalletCommand { @@ -367,7 +367,7 @@ pub fn process_command(config: &WalletConfig) -> Result