From 5f6d5660aa9a38d140a24da0460735efb64e89bc Mon Sep 17 00:00:00 2001 From: "OEM Configuration (temporary user)" Date: Sun, 29 Jul 2018 00:10:06 -0700 Subject: [PATCH] Fixed broken tests after rebase --- src/bank.rs | 24 ++++++++++++------------ src/entry_writer.rs | 3 +-- src/ledger.rs | 41 ++++++++++++++++++++++++++++++++--------- src/mint.rs | 4 ++-- src/thin_client.rs | 14 +++++++------- src/transaction.rs | 35 ++++++++++++++++++----------------- 6 files changed, 72 insertions(+), 49 deletions(-) diff --git a/src/bank.rs b/src/bank.rs index 5cbab2664f1f8c..300031a79550a1 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -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) } @@ -264,15 +264,15 @@ impl Bank { fn apply_credits(&self, tx: &Transaction, balances: &mut HashMap) { 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) => { @@ -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"); @@ -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"); @@ -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"); } diff --git a/src/entry_writer.rs b/src/entry_writer.rs index a7dc17908e545c..2cc7f033aa0557 100644 --- a/src/entry_writer.rs +++ b/src/entry_writer.rs @@ -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] @@ -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(); diff --git a/src/ledger.rs b/src/ledger.rs index 3f296d20b1bf08..44236b9d7b9304 100644 --- a/src/ledger.rs +++ b/src/ledger.rs @@ -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() { @@ -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]; @@ -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)); diff --git a/src/mint.rs b/src/mint.rs index f2324f4eec88eb..162c1b846aa0e8 100644 --- a/src/mint.rs +++ b/src/mint.rs @@ -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); } } diff --git a/src/thin_client.rs b/src/thin_client.rs index 762dbdf36e3c3d..7178e8b56854ba 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -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(); @@ -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); } @@ -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, @@ -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 @@ -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( diff --git a/src/transaction.rs b/src/transaction.rs index aeb34fa62013fd..e2245b4784ae81 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -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; @@ -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), /// Tell a payment plan acknowledge the given `DateTime` has past. ApplyTimestamp(DateTime), @@ -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) } @@ -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) } @@ -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; } } @@ -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(), @@ -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()); @@ -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! } } @@ -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! } }