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 {