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.
This commit is contained in:
Greg Fitzgerald 2019-03-06 22:12:14 -07:00
parent 10b16753af
commit a277f3e816
3 changed files with 57 additions and 45 deletions

View File

@ -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],

View File

@ -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<Utc>,
) -> 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)
}
}

View File

@ -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<Utc>,
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<SystemInstruction> {