From 7a0bc7d88800fa54b5120eb86932702b36a2ce97 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Sat, 10 Mar 2018 16:55:39 -0700 Subject: [PATCH] Move smart contract fields into their own struct --- src/accountant.rs | 20 ++++++++++---------- src/mint.rs | 2 +- src/transaction.rs | 39 +++++++++++++++++++++++++++------------ 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/accountant.rs b/src/accountant.rs index 3113cf9200..88e8bbc6fa 100644 --- a/src/accountant.rs +++ b/src/accountant.rs @@ -109,12 +109,12 @@ impl Accountant { /// Commit funds to the 'to' party. fn complete_transaction(self: &mut Self, tr: &Transaction) { - if self.balances.contains_key(&tr.to) { - if let Some(x) = self.balances.get_mut(&tr.to) { + if self.balances.contains_key(&tr.plan.to) { + if let Some(x) = self.balances.get_mut(&tr.plan.to) { *x += tr.asset; } } else { - self.balances.insert(tr.to, tr.asset); + self.balances.insert(tr.plan.to, tr.asset); } } @@ -149,17 +149,17 @@ impl Accountant { return Err(AccountingError::InvalidTransferSignature); } - if !tr.unless_any.is_empty() { + if !tr.plan.unless_any.is_empty() { // TODO: Check to see if the transaction is expired. } - if !Self::is_deposit(allow_deposits, &tr.from, &tr.to) { + if !Self::is_deposit(allow_deposits, &tr.from, &tr.plan.to) { if let Some(x) = self.balances.get_mut(&tr.from) { *x -= tr.asset; } } - if !self.all_satisfied(&tr.if_all) { + if !self.all_satisfied(&tr.plan.if_all) { self.pending.insert(tr.sig, tr.clone()); return Ok(()); } @@ -175,7 +175,7 @@ impl Accountant { // if Signature(from) is in unless_any, return funds to tx.from, and remove the tx from this map. // TODO: Use find(). - for cond in &tr.unless_any { + for cond in &tr.plan.unless_any { if let Condition::Signature(pubkey) = *cond { if from == pubkey { cancel = true; @@ -220,17 +220,17 @@ impl Accountant { // Check to see if any timelocked transactions can be completed. let mut completed = vec![]; for (key, tr) in &self.pending { - for cond in &tr.if_all { + for cond in &tr.plan.if_all { if let Condition::Timestamp(dt) = *cond { if self.last_time >= dt { - if tr.if_all.len() == 1 { + if tr.plan.if_all.len() == 1 { completed.push(*key); } } } } // TODO: Add this in once we start removing constraints - //if tr.if_all.is_empty() { + //if tr.plan.if_all.is_empty() { // // TODO: Remove tr from pending // self.complete_transaction(tr); //} diff --git a/src/mint.rs b/src/mint.rs index 991a1cb8c1..0fd1e0b835 100644 --- a/src/mint.rs +++ b/src/mint.rs @@ -63,7 +63,7 @@ mod tests { fn test_create_events() { let mut events = Mint::new(100).create_events().into_iter(); if let Event::Transaction(tr) = events.next().unwrap() { - assert_eq!(tr.from, tr.to); + assert_eq!(tr.from, tr.plan.to); } assert_eq!(events.next(), None); } diff --git a/src/transaction.rs b/src/transaction.rs index 046d8485a0..86a2f3f756 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -13,11 +13,16 @@ pub enum Condition { } #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] -pub struct Transaction { - pub from: PublicKey, +pub struct SpendingPlan { pub to: PublicKey, pub if_all: Vec, pub unless_any: Vec, +} + +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +pub struct Transaction { + pub from: PublicKey, + pub plan: SpendingPlan, pub asset: T, pub last_id: Hash, pub sig: Signature, @@ -25,11 +30,14 @@ pub struct Transaction { impl Transaction { pub fn new(from_keypair: &KeyPair, to: PublicKey, asset: T, last_id: Hash) -> Self { - let mut tr = Transaction { - from: from_keypair.pubkey(), + let plan = SpendingPlan { to, if_all: vec![], unless_any: vec![], + }; + let mut tr = Transaction { + from: from_keypair.pubkey(), + plan, asset, last_id, sig: Signature::default(), @@ -46,11 +54,14 @@ impl Transaction { last_id: Hash, ) -> Self { let from = from_keypair.pubkey(); - let mut tr = Transaction { - from, + let plan = SpendingPlan { to, if_all: vec![Condition::Timestamp(dt)], unless_any: vec![Condition::Signature(from)], + }; + let mut tr = Transaction { + from, + plan, asset, last_id, sig: Signature::default(), @@ -60,11 +71,12 @@ impl Transaction { } fn get_sign_data(&self) -> Vec { + let plan = &self.plan; serialize(&( &self.from, - &self.to, - &self.if_all, - &self.unless_any, + &plan.to, + &plan.if_all, + &plan.unless_any, &self.asset, &self.last_id, )).unwrap() @@ -108,11 +120,14 @@ mod tests { #[test] fn test_serialize_claim() { - let claim0 = Transaction { - from: Default::default(), + let plan = SpendingPlan { to: Default::default(), if_all: Default::default(), unless_any: Default::default(), + }; + let claim0 = Transaction { + from: Default::default(), + plan, asset: 0u8, last_id: Default::default(), sig: Default::default(), @@ -142,7 +157,7 @@ mod tests { let zero = Hash::default(); let mut tr = Transaction::new(&keypair0, pubkey1, hash(b"hello, world"), zero); tr.sign(&keypair0); - tr.to = thief_keypair.pubkey(); // <-- attack! + tr.plan.to = thief_keypair.pubkey(); // <-- attack! assert!(!tr.verify()); } }