Resurrect the tests
This commit is contained in:
@ -6,6 +6,7 @@ use solana_budget_api::budget_instruction::BudgetInstruction;
|
|||||||
use solana_budget_api::budget_state::{BudgetError, BudgetState};
|
use solana_budget_api::budget_state::{BudgetError, BudgetState};
|
||||||
use solana_budget_api::payment_plan::Witness;
|
use solana_budget_api::payment_plan::Witness;
|
||||||
use solana_sdk::account::KeyedAccount;
|
use solana_sdk::account::KeyedAccount;
|
||||||
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
|
||||||
/// Process a Witness Signature. Any payment plans waiting on this signature
|
/// Process a Witness Signature. Any payment plans waiting on this signature
|
||||||
/// will progress one step.
|
/// will progress one step.
|
||||||
@ -78,10 +79,6 @@ fn apply_debits(
|
|||||||
keyed_accounts: &mut [KeyedAccount],
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
instruction: &BudgetInstruction,
|
instruction: &BudgetInstruction,
|
||||||
) -> Result<(), BudgetError> {
|
) -> Result<(), BudgetError> {
|
||||||
if !keyed_accounts[0].account.userdata.is_empty() {
|
|
||||||
trace!("source is pending");
|
|
||||||
return Err(BudgetError::SourceIsPendingContract);
|
|
||||||
}
|
|
||||||
match instruction {
|
match instruction {
|
||||||
BudgetInstruction::InitializeAccount(expr) => {
|
BudgetInstruction::InitializeAccount(expr) => {
|
||||||
let expr = expr.clone();
|
let expr = expr.clone();
|
||||||
@ -143,21 +140,18 @@ fn apply_debits(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Budget DSL contract interface
|
|
||||||
/// * accounts[0] - The source of the lamports
|
|
||||||
/// * accounts[1] - The contract context. Once the contract has been completed, the lamports can
|
|
||||||
/// be spent from this account .
|
|
||||||
pub fn process_instruction(
|
pub fn process_instruction(
|
||||||
|
_program_id: &Pubkey,
|
||||||
keyed_accounts: &mut [KeyedAccount],
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) -> Result<(), BudgetError> {
|
) -> Result<(), BudgetError> {
|
||||||
if let Ok(instruction) = deserialize(data) {
|
let instruction = deserialize(data).map_err(|err| {
|
||||||
trace!("process_instruction: {:?}", instruction);
|
info!("Invalid transaction userdata: {:?} {:?}", data, err);
|
||||||
apply_debits(keyed_accounts, &instruction)
|
BudgetError::UserdataDeserializeFailure
|
||||||
} else {
|
})?;
|
||||||
info!("Invalid transaction userdata: {:?}", data);
|
|
||||||
Err(BudgetError::UserdataDeserializeFailure)
|
trace!("process_instruction: {:?}", instruction);
|
||||||
}
|
apply_debits(keyed_accounts, &instruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -169,9 +163,9 @@ mod test {
|
|||||||
use solana_sdk::account::Account;
|
use solana_sdk::account::Account;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
|
use solana_sdk::system_program;
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
|
|
||||||
// TODO: This is wrong and will only work with single-instruction transactions.
|
|
||||||
fn process_transaction(
|
fn process_transaction(
|
||||||
tx: &Transaction,
|
tx: &Transaction,
|
||||||
tx_accounts: &mut [Account],
|
tx_accounts: &mut [Account],
|
||||||
@ -199,10 +193,10 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_unsigned_witness_key() {
|
fn test_unsigned_witness_key() {
|
||||||
let mut accounts = vec![
|
let mut accounts = vec![
|
||||||
Account::new(1, 0, id()),
|
Account::new(1, 0, system_program::id()),
|
||||||
Account::new(0, 512, id()),
|
Account::new(0, 0, system_program::id()),
|
||||||
Account::new(0, 0, id()),
|
Account::new(0, 0, system_program::id()),
|
||||||
Account::new(0, 0, id()),
|
Account::new(0, 0, system_program::id()),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Initialize BudgetState
|
// Initialize BudgetState
|
||||||
@ -239,10 +233,10 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_unsigned_timestamp() {
|
fn test_unsigned_timestamp() {
|
||||||
let mut accounts = vec![
|
let mut accounts = vec![
|
||||||
Account::new(1, 0, id()),
|
Account::new(1, 0, system_program::id()),
|
||||||
Account::new(0, 512, id()),
|
Account::new(0, 0, system_program::id()),
|
||||||
Account::new(0, 0, id()),
|
Account::new(0, 0, system_program::id()),
|
||||||
Account::new(0, 0, id()),
|
Account::new(0, 0, system_program::id()),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Initialize BudgetState
|
// Initialize BudgetState
|
||||||
@ -280,9 +274,9 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_transfer_on_date() {
|
fn test_transfer_on_date() {
|
||||||
let mut accounts = vec![
|
let mut accounts = vec![
|
||||||
Account::new(1, 0, id()),
|
Account::new(1, 0, system_program::id()),
|
||||||
Account::new(0, 512, id()),
|
Account::new(0, 0, system_program::id()),
|
||||||
Account::new(0, 0, id()),
|
Account::new(0, 0, system_program::id()),
|
||||||
];
|
];
|
||||||
let from_account = 0;
|
let from_account = 0;
|
||||||
let contract_account = 1;
|
let contract_account = 1;
|
||||||
@ -356,9 +350,9 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_cancel_transfer() {
|
fn test_cancel_transfer() {
|
||||||
let mut accounts = vec![
|
let mut accounts = vec![
|
||||||
Account::new(1, 0, id()),
|
Account::new(1, 0, system_program::id()),
|
||||||
Account::new(0, 512, id()),
|
Account::new(0, 0, system_program::id()),
|
||||||
Account::new(0, 0, id()),
|
Account::new(0, 0, system_program::id()),
|
||||||
];
|
];
|
||||||
let from_account = 0;
|
let from_account = 0;
|
||||||
let contract_account = 1;
|
let contract_account = 1;
|
||||||
@ -422,41 +416,4 @@ mod test {
|
|||||||
assert_eq!(accounts[contract_account].lamports, 0);
|
assert_eq!(accounts[contract_account].lamports, 0);
|
||||||
assert_eq!(accounts[pay_account].lamports, 0);
|
assert_eq!(accounts[pay_account].lamports, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_userdata_too_small() {
|
|
||||||
let mut accounts = vec![
|
|
||||||
Account::new(1, 0, id()),
|
|
||||||
Account::new(1, 0, id()), // <== userdata is 0, which is not enough
|
|
||||||
Account::new(1, 0, id()),
|
|
||||||
];
|
|
||||||
let from = Keypair::new();
|
|
||||||
let contract = Keypair::new();
|
|
||||||
let to = Keypair::new();
|
|
||||||
let tx = BudgetTransaction::new_on_date(
|
|
||||||
&from,
|
|
||||||
to.pubkey(),
|
|
||||||
contract.pubkey(),
|
|
||||||
Utc::now(),
|
|
||||||
from.pubkey(),
|
|
||||||
None,
|
|
||||||
1,
|
|
||||||
Hash::default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
assert!(process_transaction(&tx, &mut accounts).is_err());
|
|
||||||
assert!(BudgetState::deserialize(&accounts[1].userdata).is_err());
|
|
||||||
|
|
||||||
let tx = BudgetTransaction::new_timestamp(
|
|
||||||
&from,
|
|
||||||
contract.pubkey(),
|
|
||||||
to.pubkey(),
|
|
||||||
Utc::now(),
|
|
||||||
Hash::default(),
|
|
||||||
);
|
|
||||||
assert!(process_transaction(&tx, &mut accounts).is_err());
|
|
||||||
assert!(BudgetState::deserialize(&accounts[1].userdata).is_err());
|
|
||||||
|
|
||||||
// Success if there was no panic...
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ use solana_sdk::solana_entrypoint;
|
|||||||
|
|
||||||
solana_entrypoint!(entrypoint);
|
solana_entrypoint!(entrypoint);
|
||||||
fn entrypoint(
|
fn entrypoint(
|
||||||
_program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
keyed_accounts: &mut [KeyedAccount],
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
_tick_height: u64,
|
_tick_height: u64,
|
||||||
@ -18,5 +18,5 @@ fn entrypoint(
|
|||||||
|
|
||||||
trace!("process_instruction: {:?}", data);
|
trace!("process_instruction: {:?}", data);
|
||||||
trace!("keyed_accounts: {:?}", keyed_accounts);
|
trace!("keyed_accounts: {:?}", keyed_accounts);
|
||||||
process_instruction(keyed_accounts, data).map_err(|_| ProgramError::GenericError)
|
process_instruction(program_id, keyed_accounts, data).map_err(|_| ProgramError::GenericError)
|
||||||
}
|
}
|
||||||
|
@ -43,12 +43,18 @@ impl BudgetInstruction {
|
|||||||
to: Pubkey,
|
to: Pubkey,
|
||||||
dt: DateTime<Utc>,
|
dt: DateTime<Utc>,
|
||||||
) -> BuilderInstruction {
|
) -> BuilderInstruction {
|
||||||
let keys = vec![(from, true), (contract, false), (to, false)];
|
let mut keys = vec![(from, true), (contract, false)];
|
||||||
|
if from != to {
|
||||||
|
keys.push((to, false));
|
||||||
|
}
|
||||||
BuilderInstruction::new(id(), &BudgetInstruction::ApplyTimestamp(dt), keys)
|
BuilderInstruction::new(id(), &BudgetInstruction::ApplyTimestamp(dt), keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_apply_signature(from: Pubkey, contract: Pubkey, to: Pubkey) -> BuilderInstruction {
|
pub fn new_apply_signature(from: Pubkey, contract: Pubkey, to: Pubkey) -> BuilderInstruction {
|
||||||
let keys = vec![(from, true), (contract, false), (to, false)];
|
let mut keys = vec![(from, true), (contract, false)];
|
||||||
|
if from != to {
|
||||||
|
keys.push((to, false));
|
||||||
|
}
|
||||||
BuilderInstruction::new(id(), &BudgetInstruction::ApplySignature, keys)
|
BuilderInstruction::new(id(), &BudgetInstruction::ApplySignature, keys)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,9 +196,9 @@ pub fn process_transaction<F, E>(
|
|||||||
process_instruction: F,
|
process_instruction: F,
|
||||||
) -> Result<(), E>
|
) -> Result<(), E>
|
||||||
where
|
where
|
||||||
F: Fn(&mut [KeyedAccount], &[u8]) -> Result<(), E>,
|
F: Fn(&Pubkey, &mut [KeyedAccount], &[u8]) -> Result<(), E>,
|
||||||
{
|
{
|
||||||
for ix in &tx.instructions {
|
for (i, ix) in tx.instructions.iter().enumerate() {
|
||||||
let mut ix_accounts = get_subset_unchecked_mut(tx_accounts, &ix.accounts);
|
let mut ix_accounts = get_subset_unchecked_mut(tx_accounts, &ix.accounts);
|
||||||
let mut keyed_accounts: Vec<_> = ix
|
let mut keyed_accounts: Vec<_> = ix
|
||||||
.accounts
|
.accounts
|
||||||
@ -212,7 +212,13 @@ where
|
|||||||
.map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account))
|
.map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
process_instruction(&mut keyed_accounts, &ix.userdata)?;
|
let program_id = tx.program_id(i);
|
||||||
|
if system_program::check_id(&program_id) {
|
||||||
|
solana_system_program::entrypoint(&program_id, &mut keyed_accounts, &ix.userdata, 0)
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
process_instruction(&program_id, &mut keyed_accounts, &ix.userdata)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user