Skip to content

Commit

Permalink
Fixed broken tests after rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
carllin committed Aug 2, 2018
1 parent cd8a4a7 commit 5f6d566
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 49 deletions.
24 changes: 12 additions & 12 deletions src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,12 @@ impl Bank {
// Negative fee shouldn't be possible here, we checked for valid fees when
// deserializing the transactions
let total_cost_result = tx.instructions.iter().try_fold(tx.fee, |total, i| {
if let Instruction::NewContract(contract) = i {
if contract.tokens < 0 {
if let Instruction::NewContract(box_contract) = i {
if box_contract.tokens < 0 {
return Err(BankError::NegativeTokens);
}

Ok(total + contract.tokens)
Ok(total + box_contract.tokens)
} else {
Ok(total)
}
Expand Down Expand Up @@ -264,15 +264,15 @@ impl Bank {
fn apply_credits(&self, tx: &Transaction, balances: &mut HashMap<PublicKey, i64>) {
for i in &tx.instructions {
match i {
Instruction::NewContract(contract) => {
let plan = contract.plan.clone();
Instruction::NewContract(box_contract) => {
let plan = box_contract.plan.clone();
if let Some(payment) = plan.final_payment() {
self.apply_payment(&payment, balances);
} else {
let mut pending = self.pending
.write()
.expect("'pending' write lock in apply_credits");
pending.insert(contract.id, plan);
pending.insert(box_contract.id, plan);
}
}
Instruction::ApplyTimestamp(dt) => {
Expand Down Expand Up @@ -444,8 +444,8 @@ impl Bank {
panic!("invalid ledger, first transaction is empty");
}

let deposit = if let Instruction::NewContract(contract) = &tx.instructions[0] {
contract.plan.final_payment()
let deposit = if let Instruction::NewContract(box_contract) = &tx.instructions[0] {
box_contract.plan.final_payment()
} else {
None
}.expect("invalid ledger, needs to start with a contract");
Expand Down Expand Up @@ -503,8 +503,8 @@ impl Bank {
// Check to see if any timelocked transactions can be completed.
let mut completed = vec![];

// Hold 'pending' write lock until the end of this function. Otherwise another thread can
// double-spend if it enters before the modified plan is removed from 'pending'.
// Hold 'pending' write lock until the end of this function. Otherwise another thread can
// double-spend if it enters before the modified plan is removed from 'pending'.
let mut pending = self.pending
.write()
.expect("'pending' write lock in apply_timestamp");
Expand Down Expand Up @@ -703,8 +703,8 @@ mod tests {
.unwrap();

let contract_id;
if let Instruction::NewContract(contract) = &tx.instructions[0] {
contract_id = contract.id;
if let Instruction::NewContract(box_contract) = &tx.instructions[0] {
contract_id = box_contract.id;
} else {
panic!("expecting contract instruction");
}
Expand Down
3 changes: 1 addition & 2 deletions src/entry_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ mod tests {
use packet::BLOB_DATA_SIZE;
use signature::{KeyPair, KeyPairUtil};
use std::io::Cursor;
use std::str;
use transaction::{Transaction, BASE_TRANSACTION_SIZE, MAX_INSTRUCTION_SIZE};

#[test]
Expand Down Expand Up @@ -153,7 +152,7 @@ mod tests {

#[test]
fn test_read_entries_from_buf() {
let mint = Mint::new(1);
let mut mint = Mint::new(1);
let mut buf = vec![];
let created_entries = mint.create_entries();
EntryWriter::write_entries(&mut buf, created_entries.clone()).unwrap();
Expand Down
41 changes: 32 additions & 9 deletions src/ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,14 +312,19 @@ pub fn next_entries(
mod tests {
use super::*;
use bincode::serialized_size;
use budget::{Budget, Condition};
use chrono::prelude::*;
use entry::{next_entry, Entry};
use hash::hash;
use packet::{BlobRecycler, BLOB_DATA_SIZE, PACKET_DATA_SIZE};
use packet::{BlobRecycler, BLOB_DATA_SIZE};
use payment_plan::Payment;
use signature::{KeyPair, KeyPairUtil};
use std;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use transaction::{Transaction, Vote, BASE_TRANSACTION_SIZE, MAX_INSTRUCTION_SIZE};
use transaction::{
Contract, Instruction, Plan, Transaction, Vote, BASE_TRANSACTION_SIZE, FEE_PER_INSTRUCTION,
MAX_INSTRUCTION_SIZE,
};

#[test]
fn test_verify_slice() {
Expand Down Expand Up @@ -399,16 +404,34 @@ mod tests {
next_id,
2,
);
let tx_large = Transaction::new(&keypair, keypair.pubkey(), 1, next_id);

let tx_small_size = serialized_size(&tx_small).unwrap();
let tx_large_size = serialized_size(&tx_large).unwrap();
// Create large transaction
let transfer_value = 1000;
let date_condition = (
Condition::Timestamp(Utc::now(), keypair.pubkey()),
Payment {
tokens: transfer_value,
to: keypair.pubkey(),
},
);

let budget = Budget::Or(date_condition.clone(), date_condition);
let plan = Plan::Budget(budget);
let contract = Contract::new(transfer_value, plan);
let tx_large = Transaction::new_from_instructions(
&keypair,
vec![Instruction::NewContract(Box::new(contract))],
next_id,
FEE_PER_INSTRUCTION as i64,
);

let tx_small_size = serialized_size(&tx_small).unwrap() as usize;
let tx_large_size = serialized_size(&tx_large).unwrap() as usize;
assert!(tx_small_size < tx_large_size);
assert!(tx_large_size < PACKET_DATA_SIZE as u64);
assert!(tx_large_size <= BASE_TRANSACTION_SIZE + MAX_INSTRUCTION_SIZE);

let transaction_size = BASE_TRANSACTION_SIZE + MAX_INSTRUCTION_SIZE;
// NOTE: if Entry grows to larger than a transaction, the code below falls over
let threshold = (BLOB_DATA_SIZE / transaction_size) - 1; // 256 is transaction size
let threshold = (BLOB_DATA_SIZE / (tx_small_size as usize)) - 1;

// verify no split
let transactions = vec![tx_small.clone(); threshold];
Expand All @@ -432,7 +455,7 @@ mod tests {
transactions.extend(large_transactions);

let entries0 = next_entries(&id, 0, transactions.clone());
assert!(entries0.len() > 2);
assert!(entries0.len() >= 2);
assert!(entries0[0].has_more);
assert!(!entries0[entries0.len() - 1].has_more);
assert!(entries0.verify(&id));
Expand Down
4 changes: 2 additions & 2 deletions src/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ mod tests {
fn test_create_transactions() {
let mut transactions = Mint::new(100).create_transactions().into_iter();
let tx = transactions.next().unwrap();
if let Instruction::NewContract(contract) = &tx.instructions[0] {
if let Plan::Budget(Budget::Pay(payment)) = &contract.plan {
if let Instruction::NewContract(box_contract) = &tx.instructions[0] {
if let Plan::Budget(Budget::Pay(payment)) = &box_contract.plan {
assert_eq!(tx.from, payment.to);
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/thin_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,9 +409,9 @@ mod tests {
let last_id = client.get_last_id();

let mut tr2 = Transaction::new(&alice.keypair(), bob_pubkey, 501, last_id);
if let Instruction::NewContract(contract) = &mut tr2.instructions[0] {
contract.tokens = 502;
contract.plan = Plan::Budget(Budget::new_payment(502, bob_pubkey));
if let Instruction::NewContract(box_contract) = &mut tr2.instructions[0] {
box_contract.tokens = 502;
box_contract.plan = Plan::Budget(Budget::new_payment(502, bob_pubkey));
}
let sig = client.transfer_signed(&tr2).unwrap();
client.poll_for_signature(&sig).unwrap();
Expand Down Expand Up @@ -524,7 +524,7 @@ mod tests {
let budget = Budget::Pay(payment);
let plan = Plan::Budget(budget);
let contract = Contract::new(transfer_value, plan);
let instruction = Instruction::NewContract(contract);
let instruction = Instruction::NewContract(Box::new(contract));
multi_instructions.push(instruction);
}

Expand Down Expand Up @@ -600,7 +600,7 @@ mod tests {
expected_balance += transfer_value;

let date_condition = (
Condition::Timestamp(Utc::now(), alice.pubkey()),
Timestamp(Utc::now(), alice.pubkey()),
Payment {
tokens: transfer_value,
to: bob_pubkey,
Expand All @@ -610,7 +610,7 @@ mod tests {
let budget = Budget::Or(date_condition.clone(), date_condition);
let plan = Plan::Budget(budget);
let contract = Contract::new(transfer_value, plan);
contract_instructions.push(Instruction::NewContract(contract));
contract_instructions.push(Instruction::NewContract(Box::new(contract)));
}

// Make contracts that need a signature
Expand All @@ -623,7 +623,7 @@ mod tests {
let plan = Plan::Budget(budget);
let contract = Contract::new(transfer_value, plan);
contract_ids.push(contract.id);
contract_instructions.push(Instruction::NewContract(contract));
contract_instructions.push(Instruction::NewContract(Box::new(contract)));
}

let contract_transaction = Transaction::new_from_instructions(
Expand Down
35 changes: 18 additions & 17 deletions src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub const PUB_KEY_OFFSET: usize = 80;
pub const MAX_ALLOWED_INSTRUCTIONS: usize = 20;
// The biggest current instruction is a Budget with a payment plan of 'Or' with two
// datetime 'Condition' branches. This is the serialized size of that instruction
pub const MAX_INSTRUCTION_SIZE: usize = 314;
pub const MAX_INSTRUCTION_SIZE: usize = 352;
// Serialized size of everything in the transaction excluding the instructions
pub const BASE_TRANSACTION_SIZE: usize = 168;
pub const FEE_PER_INSTRUCTION: usize = 0;
Expand Down Expand Up @@ -86,7 +86,7 @@ pub struct Vote {
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Instruction {
/// Declare and instanstansiate `Contract`.
NewContract(Contract),
NewContract(Box<Contract>),

/// Tell a payment plan acknowledge the given `DateTime` has past.
ApplyTimestamp(DateTime<Utc>),
Expand Down Expand Up @@ -150,7 +150,7 @@ impl Transaction {
let budget = Budget::Pay(payment);
let plan = Plan::Budget(budget);
let contract = Contract::new(tokens, plan);
let instruction = Instruction::NewContract(contract);
let instruction = Instruction::NewContract(Box::new(contract));
Self::new_from_instructions(from_keypair, vec![instruction], last_id, fee)
}

Expand Down Expand Up @@ -195,7 +195,7 @@ impl Transaction {
);
let plan = Plan::Budget(budget);
let contract = Contract::new(tokens, plan);
let instructions = vec![Instruction::NewContract(contract)];
let instructions = vec![Instruction::NewContract(Box::new(contract))];
Self::new_from_instructions(from_keypair, instructions, last_id, 0)
}

Expand Down Expand Up @@ -230,8 +230,8 @@ impl Transaction {
}

for i in &self.instructions {
if let Instruction::NewContract(contract) = i {
if !contract.plan.verify(contract.tokens) {
if let Instruction::NewContract(contract_box) = i {
if !contract_box.plan.verify(contract_box.tokens) {
return false;
}
}
Expand Down Expand Up @@ -310,7 +310,7 @@ mod tests {
});
let plan = Plan::Budget(budget);
let contract = Contract::new(0, plan);
let instruction = Instruction::NewContract(contract);
let instruction = Instruction::NewContract(Box::new(contract));
let claim0 = Transaction {
instructions: vec![instruction],
from: Default::default(),
Expand All @@ -329,10 +329,11 @@ mod tests {
let keypair = KeyPair::new();
let pubkey = keypair.pubkey();
let mut tx = Transaction::new(&keypair, pubkey, 42, zero);
if let Instruction::NewContract(contract) = &mut tx.instructions[0] {
contract.tokens = 1_000_000; // <-- attack, part 1!
if let Plan::Budget(Budget::Pay(ref mut payment)) = contract.plan {
payment.tokens = contract.tokens; // <-- attack, part 2!
if let Instruction::NewContract(contract_box) = &mut tx.instructions[0] {
let tokens = 1_000_000; // <-- attack, part 1!
contract_box.tokens = tokens;
if let Plan::Budget(Budget::Pay(ref mut payment)) = contract_box.plan {
payment.tokens = tokens; // <-- attack, part 2!
}
}
assert!(tx.verify_plan());
Expand All @@ -347,8 +348,8 @@ mod tests {
let pubkey1 = keypair1.pubkey();
let zero = Hash::default();
let mut tx = Transaction::new(&keypair0, pubkey1, 42, zero);
if let Instruction::NewContract(contract) = &mut tx.instructions[0] {
if let Plan::Budget(Budget::Pay(ref mut payment)) = contract.plan {
if let Instruction::NewContract(contract_box) = &mut tx.instructions[0] {
if let Plan::Budget(Budget::Pay(ref mut payment)) = contract_box.plan {
payment.to = thief_keypair.pubkey(); // <-- attack!
}
}
Expand All @@ -371,16 +372,16 @@ mod tests {
let keypair1 = KeyPair::new();
let zero = Hash::default();
let mut tx = Transaction::new(&keypair0, keypair1.pubkey(), 1, zero);
if let Instruction::NewContract(contract) = &mut tx.instructions[0] {
if let Plan::Budget(Budget::Pay(ref mut payment)) = contract.plan {
if let Instruction::NewContract(contract_box) = &mut tx.instructions[0] {
if let Plan::Budget(Budget::Pay(ref mut payment)) = contract_box.plan {
payment.tokens = 2; // <-- attack!
}
}
assert!(!tx.verify_plan());

// Also, ensure all branchs of the plan spend all tokens
if let Instruction::NewContract(contract) = &mut tx.instructions[0] {
if let Plan::Budget(Budget::Pay(ref mut payment)) = contract.plan {
if let Instruction::NewContract(contract_box) = &mut tx.instructions[0] {
if let Plan::Budget(Budget::Pay(ref mut payment)) = contract_box.plan {
payment.tokens = 0; // <-- whoops!
}
}
Expand Down

0 comments on commit 5f6d566

Please sign in to comment.