Remove Instruction wrapper structs and name functions after enum fields
This commit is contained in:
		@@ -6,7 +6,7 @@ use chrono::prelude::{DateTime, Utc};
 | 
			
		||||
use serde_derive::{Deserialize, Serialize};
 | 
			
		||||
use solana_sdk::instruction::{AccountMeta, Instruction};
 | 
			
		||||
use solana_sdk::pubkey::Pubkey;
 | 
			
		||||
use solana_sdk::system_instruction::SystemInstruction;
 | 
			
		||||
use solana_sdk::system_instruction;
 | 
			
		||||
 | 
			
		||||
/// A smart contract.
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
 | 
			
		||||
@@ -30,93 +30,90 @@ pub enum BudgetInstruction {
 | 
			
		||||
    ApplySignature,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl BudgetInstruction {
 | 
			
		||||
    fn new_initialize_account(contract: &Pubkey, expr: BudgetExpr) -> Instruction {
 | 
			
		||||
        let mut keys = vec![];
 | 
			
		||||
        if let BudgetExpr::Pay(payment) = &expr {
 | 
			
		||||
            keys.push(AccountMeta::new(payment.to, false));
 | 
			
		||||
        }
 | 
			
		||||
        keys.push(AccountMeta::new(*contract, false));
 | 
			
		||||
        Instruction::new(id(), &BudgetInstruction::InitializeAccount(expr), keys)
 | 
			
		||||
fn initialize_account(contract: &Pubkey, expr: BudgetExpr) -> Instruction {
 | 
			
		||||
    let mut keys = vec![];
 | 
			
		||||
    if let BudgetExpr::Pay(payment) = &expr {
 | 
			
		||||
        keys.push(AccountMeta::new(payment.to, false));
 | 
			
		||||
    }
 | 
			
		||||
    keys.push(AccountMeta::new(*contract, false));
 | 
			
		||||
    Instruction::new(id(), &BudgetInstruction::InitializeAccount(expr), keys)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    pub fn new_account(
 | 
			
		||||
        from: &Pubkey,
 | 
			
		||||
        contract: &Pubkey,
 | 
			
		||||
        lamports: u64,
 | 
			
		||||
        expr: BudgetExpr,
 | 
			
		||||
    ) -> Vec<Instruction> {
 | 
			
		||||
        if !expr.verify(lamports) {
 | 
			
		||||
            panic!("invalid budget expression");
 | 
			
		||||
        }
 | 
			
		||||
        let space = serialized_size(&BudgetState::new(expr.clone())).unwrap();
 | 
			
		||||
        vec![
 | 
			
		||||
            SystemInstruction::new_account(&from, contract, lamports, space, &id()),
 | 
			
		||||
            BudgetInstruction::new_initialize_account(contract, expr),
 | 
			
		||||
        ]
 | 
			
		||||
pub fn create_account(
 | 
			
		||||
    from: &Pubkey,
 | 
			
		||||
    contract: &Pubkey,
 | 
			
		||||
    lamports: u64,
 | 
			
		||||
    expr: BudgetExpr,
 | 
			
		||||
) -> Vec<Instruction> {
 | 
			
		||||
    if !expr.verify(lamports) {
 | 
			
		||||
        panic!("invalid budget expression");
 | 
			
		||||
    }
 | 
			
		||||
    let space = serialized_size(&BudgetState::new(expr.clone())).unwrap();
 | 
			
		||||
    vec![
 | 
			
		||||
        system_instruction::create_account(&from, contract, lamports, space, &id()),
 | 
			
		||||
        initialize_account(contract, expr),
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    /// Create a new payment script.
 | 
			
		||||
    pub fn new_payment(from: &Pubkey, to: &Pubkey, lamports: u64) -> Vec<Instruction> {
 | 
			
		||||
        let contract = Pubkey::new_rand();
 | 
			
		||||
        let expr = BudgetExpr::new_payment(lamports, to);
 | 
			
		||||
        Self::new_account(from, &contract, lamports, expr)
 | 
			
		||||
    }
 | 
			
		||||
/// Create a new payment script.
 | 
			
		||||
pub fn payment(from: &Pubkey, to: &Pubkey, lamports: u64) -> Vec<Instruction> {
 | 
			
		||||
    let contract = Pubkey::new_rand();
 | 
			
		||||
    let expr = BudgetExpr::new_payment(lamports, to);
 | 
			
		||||
    create_account(from, &contract, lamports, expr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    /// Create a future payment script.
 | 
			
		||||
    pub fn new_on_date(
 | 
			
		||||
        from: &Pubkey,
 | 
			
		||||
        to: &Pubkey,
 | 
			
		||||
        contract: &Pubkey,
 | 
			
		||||
        dt: DateTime<Utc>,
 | 
			
		||||
        dt_pubkey: &Pubkey,
 | 
			
		||||
        cancelable: Option<Pubkey>,
 | 
			
		||||
        lamports: u64,
 | 
			
		||||
    ) -> Vec<Instruction> {
 | 
			
		||||
        let expr =
 | 
			
		||||
            BudgetExpr::new_cancelable_future_payment(dt, dt_pubkey, lamports, to, cancelable);
 | 
			
		||||
        Self::new_account(from, contract, lamports, expr)
 | 
			
		||||
    }
 | 
			
		||||
/// Create a future payment script.
 | 
			
		||||
pub fn on_date(
 | 
			
		||||
    from: &Pubkey,
 | 
			
		||||
    to: &Pubkey,
 | 
			
		||||
    contract: &Pubkey,
 | 
			
		||||
    dt: DateTime<Utc>,
 | 
			
		||||
    dt_pubkey: &Pubkey,
 | 
			
		||||
    cancelable: Option<Pubkey>,
 | 
			
		||||
    lamports: u64,
 | 
			
		||||
) -> Vec<Instruction> {
 | 
			
		||||
    let expr = BudgetExpr::new_cancelable_future_payment(dt, dt_pubkey, lamports, to, cancelable);
 | 
			
		||||
    create_account(from, contract, lamports, expr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    /// Create a multisig payment script.
 | 
			
		||||
    pub fn new_when_signed(
 | 
			
		||||
        from: &Pubkey,
 | 
			
		||||
        to: &Pubkey,
 | 
			
		||||
        contract: &Pubkey,
 | 
			
		||||
        witness: &Pubkey,
 | 
			
		||||
        cancelable: Option<Pubkey>,
 | 
			
		||||
        lamports: u64,
 | 
			
		||||
    ) -> Vec<Instruction> {
 | 
			
		||||
        let expr = BudgetExpr::new_cancelable_authorized_payment(witness, lamports, to, cancelable);
 | 
			
		||||
        Self::new_account(from, contract, lamports, expr)
 | 
			
		||||
    }
 | 
			
		||||
/// Create a multisig payment script.
 | 
			
		||||
pub fn when_signed(
 | 
			
		||||
    from: &Pubkey,
 | 
			
		||||
    to: &Pubkey,
 | 
			
		||||
    contract: &Pubkey,
 | 
			
		||||
    witness: &Pubkey,
 | 
			
		||||
    cancelable: Option<Pubkey>,
 | 
			
		||||
    lamports: u64,
 | 
			
		||||
) -> Vec<Instruction> {
 | 
			
		||||
    let expr = BudgetExpr::new_cancelable_authorized_payment(witness, lamports, to, cancelable);
 | 
			
		||||
    create_account(from, contract, lamports, expr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    pub fn new_apply_timestamp(
 | 
			
		||||
        from: &Pubkey,
 | 
			
		||||
        contract: &Pubkey,
 | 
			
		||||
        to: &Pubkey,
 | 
			
		||||
        dt: DateTime<Utc>,
 | 
			
		||||
    ) -> Instruction {
 | 
			
		||||
        let mut account_metas = vec![
 | 
			
		||||
            AccountMeta::new(*from, true),
 | 
			
		||||
            AccountMeta::new(*contract, false),
 | 
			
		||||
        ];
 | 
			
		||||
        if from != to {
 | 
			
		||||
            account_metas.push(AccountMeta::new(*to, false));
 | 
			
		||||
        }
 | 
			
		||||
        Instruction::new(id(), &BudgetInstruction::ApplyTimestamp(dt), account_metas)
 | 
			
		||||
pub fn apply_timestamp(
 | 
			
		||||
    from: &Pubkey,
 | 
			
		||||
    contract: &Pubkey,
 | 
			
		||||
    to: &Pubkey,
 | 
			
		||||
    dt: DateTime<Utc>,
 | 
			
		||||
) -> Instruction {
 | 
			
		||||
    let mut account_metas = vec![
 | 
			
		||||
        AccountMeta::new(*from, true),
 | 
			
		||||
        AccountMeta::new(*contract, false),
 | 
			
		||||
    ];
 | 
			
		||||
    if from != to {
 | 
			
		||||
        account_metas.push(AccountMeta::new(*to, false));
 | 
			
		||||
    }
 | 
			
		||||
    Instruction::new(id(), &BudgetInstruction::ApplyTimestamp(dt), account_metas)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    pub fn new_apply_signature(from: &Pubkey, contract: &Pubkey, to: &Pubkey) -> Instruction {
 | 
			
		||||
        let mut account_metas = vec![
 | 
			
		||||
            AccountMeta::new(*from, true),
 | 
			
		||||
            AccountMeta::new(*contract, false),
 | 
			
		||||
        ];
 | 
			
		||||
        if from != to {
 | 
			
		||||
            account_metas.push(AccountMeta::new(*to, false));
 | 
			
		||||
        }
 | 
			
		||||
        Instruction::new(id(), &BudgetInstruction::ApplySignature, account_metas)
 | 
			
		||||
pub fn apply_signature(from: &Pubkey, contract: &Pubkey, to: &Pubkey) -> Instruction {
 | 
			
		||||
    let mut account_metas = vec![
 | 
			
		||||
        AccountMeta::new(*from, true),
 | 
			
		||||
        AccountMeta::new(*contract, false),
 | 
			
		||||
    ];
 | 
			
		||||
    if from != to {
 | 
			
		||||
        account_metas.push(AccountMeta::new(*to, false));
 | 
			
		||||
    }
 | 
			
		||||
    Instruction::new(id(), &BudgetInstruction::ApplySignature, account_metas)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
@@ -128,7 +125,7 @@ mod tests {
 | 
			
		||||
    fn test_budget_instruction_verify() {
 | 
			
		||||
        let alice_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let bob_pubkey = Pubkey::new_rand();
 | 
			
		||||
        BudgetInstruction::new_payment(&alice_pubkey, &bob_pubkey, 1); // No panic! indicates success.
 | 
			
		||||
        payment(&alice_pubkey, &bob_pubkey, 1); // No panic! indicates success.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
@@ -138,7 +135,7 @@ mod tests {
 | 
			
		||||
        let bob_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let budget_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let expr = BudgetExpr::new_payment(2, &bob_pubkey);
 | 
			
		||||
        BudgetInstruction::new_account(&alice_pubkey, &budget_pubkey, 1, expr);
 | 
			
		||||
        create_account(&alice_pubkey, &budget_pubkey, 1, expr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
@@ -148,6 +145,6 @@ mod tests {
 | 
			
		||||
        let bob_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let budget_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let expr = BudgetExpr::new_payment(1, &bob_pubkey);
 | 
			
		||||
        BudgetInstruction::new_account(&alice_pubkey, &budget_pubkey, 2, expr);
 | 
			
		||||
        create_account(&alice_pubkey, &budget_pubkey, 2, expr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -143,7 +143,7 @@ pub fn process_instruction(
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    use super::*;
 | 
			
		||||
    use crate::budget_instruction::BudgetInstruction;
 | 
			
		||||
    use crate::budget_instruction;
 | 
			
		||||
    use crate::id;
 | 
			
		||||
    use solana_runtime::bank::Bank;
 | 
			
		||||
    use solana_runtime::bank_client::BankClient;
 | 
			
		||||
@@ -166,7 +166,7 @@ mod tests {
 | 
			
		||||
        let bank_client = BankClient::new(&bank);
 | 
			
		||||
        let alice_pubkey = alice_keypair.pubkey();
 | 
			
		||||
        let bob_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let instructions = BudgetInstruction::new_payment(&alice_pubkey, &bob_pubkey, 100);
 | 
			
		||||
        let instructions = budget_instruction::payment(&alice_pubkey, &bob_pubkey, 100);
 | 
			
		||||
        let message = Message::new(instructions);
 | 
			
		||||
        bank_client
 | 
			
		||||
            .process_message(&[&alice_keypair], message)
 | 
			
		||||
@@ -184,7 +184,7 @@ mod tests {
 | 
			
		||||
        let budget_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let bob_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let witness = Pubkey::new_rand();
 | 
			
		||||
        let instructions = BudgetInstruction::new_when_signed(
 | 
			
		||||
        let instructions = budget_instruction::when_signed(
 | 
			
		||||
            &alice_pubkey,
 | 
			
		||||
            &bob_pubkey,
 | 
			
		||||
            &budget_pubkey,
 | 
			
		||||
@@ -204,7 +204,7 @@ mod tests {
 | 
			
		||||
            .transfer(1, &alice_keypair, &mallory_pubkey)
 | 
			
		||||
            .unwrap();
 | 
			
		||||
        let instruction =
 | 
			
		||||
            BudgetInstruction::new_apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey);
 | 
			
		||||
            budget_instruction::apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey);
 | 
			
		||||
        let mut message = Message::new(vec![instruction]);
 | 
			
		||||
 | 
			
		||||
        // Attack! Part 2: Point the instruction to the expected, but unsigned, key.
 | 
			
		||||
@@ -231,7 +231,7 @@ mod tests {
 | 
			
		||||
        let budget_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let bob_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let dt = Utc::now();
 | 
			
		||||
        let instructions = BudgetInstruction::new_on_date(
 | 
			
		||||
        let instructions = budget_instruction::on_date(
 | 
			
		||||
            &alice_pubkey,
 | 
			
		||||
            &bob_pubkey,
 | 
			
		||||
            &budget_pubkey,
 | 
			
		||||
@@ -251,12 +251,8 @@ mod tests {
 | 
			
		||||
        bank_client
 | 
			
		||||
            .transfer(1, &alice_keypair, &mallory_pubkey)
 | 
			
		||||
            .unwrap();
 | 
			
		||||
        let instruction = BudgetInstruction::new_apply_timestamp(
 | 
			
		||||
            &mallory_pubkey,
 | 
			
		||||
            &budget_pubkey,
 | 
			
		||||
            &bob_pubkey,
 | 
			
		||||
            dt,
 | 
			
		||||
        );
 | 
			
		||||
        let instruction =
 | 
			
		||||
            budget_instruction::apply_timestamp(&mallory_pubkey, &budget_pubkey, &bob_pubkey, dt);
 | 
			
		||||
        let mut message = Message::new(vec![instruction]);
 | 
			
		||||
 | 
			
		||||
        // Attack! Part 2: Point the instruction to the expected, but unsigned, key.
 | 
			
		||||
@@ -282,7 +278,7 @@ mod tests {
 | 
			
		||||
        let bob_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let mallory_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let dt = Utc::now();
 | 
			
		||||
        let instructions = BudgetInstruction::new_on_date(
 | 
			
		||||
        let instructions = budget_instruction::on_date(
 | 
			
		||||
            &alice_pubkey,
 | 
			
		||||
            &bob_pubkey,
 | 
			
		||||
            &budget_pubkey,
 | 
			
		||||
@@ -303,12 +299,8 @@ mod tests {
 | 
			
		||||
        assert!(budget_state.is_pending());
 | 
			
		||||
 | 
			
		||||
        // Attack! Try to payout to mallory_pubkey
 | 
			
		||||
        let instruction = BudgetInstruction::new_apply_timestamp(
 | 
			
		||||
            &alice_pubkey,
 | 
			
		||||
            &budget_pubkey,
 | 
			
		||||
            &mallory_pubkey,
 | 
			
		||||
            dt,
 | 
			
		||||
        );
 | 
			
		||||
        let instruction =
 | 
			
		||||
            budget_instruction::apply_timestamp(&alice_pubkey, &budget_pubkey, &mallory_pubkey, dt);
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            bank_client
 | 
			
		||||
                .process_instruction(&alice_keypair, instruction)
 | 
			
		||||
@@ -329,7 +321,7 @@ mod tests {
 | 
			
		||||
        // Now, acknowledge the time in the condition occurred and
 | 
			
		||||
        // that pubkey's funds are now available.
 | 
			
		||||
        let instruction =
 | 
			
		||||
            BudgetInstruction::new_apply_timestamp(&alice_pubkey, &budget_pubkey, &bob_pubkey, dt);
 | 
			
		||||
            budget_instruction::apply_timestamp(&alice_pubkey, &budget_pubkey, &bob_pubkey, dt);
 | 
			
		||||
        bank_client
 | 
			
		||||
            .process_instruction(&alice_keypair, instruction)
 | 
			
		||||
            .unwrap();
 | 
			
		||||
@@ -348,7 +340,7 @@ mod tests {
 | 
			
		||||
        let bob_pubkey = Pubkey::new_rand();
 | 
			
		||||
        let dt = Utc::now();
 | 
			
		||||
 | 
			
		||||
        let instructions = BudgetInstruction::new_on_date(
 | 
			
		||||
        let instructions = budget_instruction::on_date(
 | 
			
		||||
            &alice_pubkey,
 | 
			
		||||
            &bob_pubkey,
 | 
			
		||||
            &budget_pubkey,
 | 
			
		||||
@@ -377,7 +369,7 @@ mod tests {
 | 
			
		||||
        assert_eq!(bank.get_balance(&alice_pubkey), 1);
 | 
			
		||||
 | 
			
		||||
        let instruction =
 | 
			
		||||
            BudgetInstruction::new_apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey);
 | 
			
		||||
            budget_instruction::apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey);
 | 
			
		||||
        bank_client
 | 
			
		||||
            .process_instruction(&mallory_keypair, instruction)
 | 
			
		||||
            .unwrap();
 | 
			
		||||
@@ -388,7 +380,7 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
        // Now, cancel the transaction. mint gets her funds back
 | 
			
		||||
        let instruction =
 | 
			
		||||
            BudgetInstruction::new_apply_signature(&alice_pubkey, &budget_pubkey, &alice_pubkey);
 | 
			
		||||
            budget_instruction::apply_signature(&alice_pubkey, &budget_pubkey, &alice_pubkey);
 | 
			
		||||
        bank_client
 | 
			
		||||
            .process_instruction(&alice_keypair, instruction)
 | 
			
		||||
            .unwrap();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user