From a277f3e81698926f22aed3af564526e909d74b18 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 6 Mar 2019 22:12:14 -0700 Subject: [PATCH] Migrate to TransactionBuilder This code wasn't updated after we started batching instructions. The current code does allocations instead of using CreateAccount. The runtime shouldn't allow that, so getting this code out of the way before we lock down the runtime. --- programs/budget/src/budget_program.rs | 7 +- programs/budget_api/src/budget_instruction.rs | 17 +++- programs/budget_api/src/budget_transaction.rs | 78 +++++++++---------- 3 files changed, 57 insertions(+), 45 deletions(-) diff --git a/programs/budget/src/budget_program.rs b/programs/budget/src/budget_program.rs index 177d639ed5..bbe5bd839d 100644 --- a/programs/budget/src/budget_program.rs +++ b/programs/budget/src/budget_program.rs @@ -90,17 +90,15 @@ fn apply_debits( keyed_accounts[0].account.lamports += payment.lamports; Ok(()) } else { - let existing = BudgetState::deserialize(&keyed_accounts[1].account.userdata).ok(); + let existing = BudgetState::deserialize(&keyed_accounts[0].account.userdata).ok(); if Some(true) == existing.map(|x| x.initialized) { trace!("contract already exists"); Err(BudgetError::ContractAlreadyExists) } else { let mut budget_state = BudgetState::default(); budget_state.pending_budget = Some(expr); - keyed_accounts[1].account.lamports += keyed_accounts[0].account.lamports; - keyed_accounts[0].account.lamports = 0; budget_state.initialized = true; - budget_state.serialize(&mut keyed_accounts[1].account.userdata) + budget_state.serialize(&mut keyed_accounts[0].account.userdata) } } } @@ -173,6 +171,7 @@ mod test { use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::transaction::Transaction; + // TODO: This is wrong and will only work with single-instruction transactions. fn process_transaction( tx: &Transaction, tx_accounts: &mut [Account], diff --git a/programs/budget_api/src/budget_instruction.rs b/programs/budget_api/src/budget_instruction.rs index f60148de4c..281f5886f4 100644 --- a/programs/budget_api/src/budget_instruction.rs +++ b/programs/budget_api/src/budget_instruction.rs @@ -32,10 +32,23 @@ impl BudgetInstruction { let mut keys = vec![]; if let BudgetExpr::Pay(payment) = &expr { keys.push((payment.to, false)); - } else { - panic!("unsupported Budget instruction"); } keys.push((contract, false)); BuilderInstruction::new(id(), &BudgetInstruction::InitializeAccount(expr), keys) } + + pub fn new_apply_timestamp( + from: Pubkey, + contract: Pubkey, + to: Pubkey, + dt: DateTime, + ) -> BuilderInstruction { + let keys = vec![(from, true), (contract, false), (to, false)]; + BuilderInstruction::new(id(), &BudgetInstruction::ApplyTimestamp(dt), keys) + } + + pub fn new_apply_signature(from: Pubkey, contract: Pubkey, to: Pubkey) -> BuilderInstruction { + let keys = vec![(from, true), (contract, false), (to, false)]; + BuilderInstruction::new(id(), &BudgetInstruction::ApplySignature, keys) + } } diff --git a/programs/budget_api/src/budget_transaction.rs b/programs/budget_api/src/budget_transaction.rs index 5df9d77025..7428d3c8fb 100644 --- a/programs/budget_api/src/budget_transaction.rs +++ b/programs/budget_api/src/budget_transaction.rs @@ -17,17 +17,17 @@ pub struct BudgetTransaction {} impl BudgetTransaction { /// Create and sign a new Transaction. Used for unit-testing. - pub fn new_payment( + #[allow(clippy::new_ret_no_self)] + fn new( from_keypair: &Keypair, - to: Pubkey, + contract: Pubkey, + expr: BudgetExpr, lamports: u64, recent_blockhash: Hash, fee: u64, ) -> Transaction { - let contract = Keypair::new().pubkey(); let from = from_keypair.pubkey(); - let payment = BudgetExpr::new_payment(lamports - fee, to); - let space = serialized_size(&BudgetState::new(payment.clone())).unwrap(); + let space = serialized_size(&BudgetState::new(expr.clone())).unwrap(); TransactionBuilder::new(fee) .push(SystemInstruction::new_program_account( from, @@ -36,10 +36,30 @@ impl BudgetTransaction { space, id(), )) - .push(BudgetInstruction::new_initialize_account(contract, payment)) + .push(BudgetInstruction::new_initialize_account(contract, expr)) .sign(&[from_keypair], recent_blockhash) } + /// Create and sign a new Transaction. Used for unit-testing. + pub fn new_payment( + from_keypair: &Keypair, + to: Pubkey, + lamports: u64, + recent_blockhash: Hash, + fee: u64, + ) -> Transaction { + let contract = Keypair::new().pubkey(); + let expr = BudgetExpr::new_payment(lamports, to); + Self::new( + from_keypair, + contract, + expr, + lamports, + recent_blockhash, + fee, + ) + } + /// Create and sign a new Witness Timestamp. Used for unit-testing. pub fn new_timestamp( from_keypair: &Keypair, @@ -48,15 +68,12 @@ impl BudgetTransaction { dt: DateTime, recent_blockhash: Hash, ) -> Transaction { - let instruction = BudgetInstruction::ApplyTimestamp(dt); - Transaction::new( - from_keypair, - &[contract, to], - id(), - &instruction, - recent_blockhash, - 0, - ) + let from = from_keypair.pubkey(); + TransactionBuilder::default() + .push(BudgetInstruction::new_apply_timestamp( + from, contract, to, dt, + )) + .sign(&[from_keypair], recent_blockhash) } /// Create and sign a new Witness Signature. Used for unit-testing. @@ -66,12 +83,10 @@ impl BudgetTransaction { to: Pubkey, recent_blockhash: Hash, ) -> Transaction { - let instruction = BudgetInstruction::ApplySignature; - let mut keys = vec![contract]; - if from_keypair.pubkey() != to { - keys.push(to); - } - Transaction::new(from_keypair, &keys, id(), &instruction, recent_blockhash, 0) + let from = from_keypair.pubkey(); + TransactionBuilder::default() + .push(BudgetInstruction::new_apply_signature(from, contract, to)) + .sign(&[from_keypair], recent_blockhash) } /// Create and sign a postdated Transaction. Used for unit-testing. @@ -102,16 +117,9 @@ impl BudgetTransaction { Box::new(BudgetExpr::new_payment(lamports, to)), ) }; - let instruction = BudgetInstruction::InitializeAccount(expr); - Transaction::new( - from_keypair, - &[contract], - id(), - &instruction, - recent_blockhash, - 0, - ) + Self::new(from_keypair, contract, expr, lamports, recent_blockhash, 0) } + /// Create and sign a multisig Transaction. pub fn new_when_signed( from_keypair: &Keypair, @@ -139,15 +147,7 @@ impl BudgetTransaction { Box::new(BudgetExpr::new_payment(lamports, to)), ) }; - let instruction = BudgetInstruction::InitializeAccount(expr); - Transaction::new( - from_keypair, - &[contract], - id(), - &instruction, - recent_blockhash, - 0, - ) + Self::new(from_keypair, contract, expr, lamports, recent_blockhash, 0) } pub fn system_instruction(tx: &Transaction, index: usize) -> Option {