From 6be3d62d8950e8eb98d7e12d79b411d5b931a36a Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 20 Mar 2018 15:43:04 -0600 Subject: [PATCH] Remove Action from spending plans --- src/accountant.rs | 10 ++++---- src/mint.rs | 4 +-- src/plan.rs | 63 ++++++++++++++-------------------------------- src/transaction.rs | 20 ++++++--------- 4 files changed, 33 insertions(+), 64 deletions(-) diff --git a/src/accountant.rs b/src/accountant.rs index 03f451f9b..cd50d00ef 100644 --- a/src/accountant.rs +++ b/src/accountant.rs @@ -5,7 +5,7 @@ use hash::Hash; use entry::Entry; use event::Event; -use plan::{Action, Plan, Witness}; +use plan::{Plan, Witness}; use transaction::Transaction; use signature::{KeyPair, PublicKey, Signature}; use mint::Mint; @@ -85,7 +85,7 @@ impl Accountant { } fn is_deposit(allow_deposits: bool, from: &PublicKey, plan: &Plan) -> bool { - if let Plan::Action(Action::Pay(ref payment)) = *plan { + if let Plan::Pay(ref payment) = *plan { allow_deposits && *from == payment.to } else { false @@ -114,7 +114,7 @@ impl Accountant { /// Commit funds to the 'to' party. fn complete_transaction(self: &mut Self, plan: &Plan) { - if let Plan::Action(Action::Pay(ref payment)) = *plan { + if let Plan::Pay(ref payment) = *plan { if self.balances.contains_key(&payment.to) { if let Some(x) = self.balances.get_mut(&payment.to) { *x += payment.tokens; @@ -288,7 +288,7 @@ mod tests { let mut acc = Accountant::new(&alice, None); let bob_pubkey = KeyPair::new().pubkey(); let mut tr = Transaction::new(&alice.keypair(), bob_pubkey, 1, alice.seed()); - if let Plan::Action(Action::Pay(ref mut payment)) = tr.plan { + if let Plan::Pay(ref mut payment) = tr.plan { payment.tokens = 2; // <-- attack! } assert_eq!( @@ -297,7 +297,7 @@ mod tests { ); // Also, ensure all branchs of the plan spend all tokens - if let Plan::Action(Action::Pay(ref mut payment)) = tr.plan { + if let Plan::Pay(ref mut payment) = tr.plan { payment.tokens = 0; // <-- whoops! } assert_eq!( diff --git a/src/mint.rs b/src/mint.rs index f2a91da87..74339cd69 100644 --- a/src/mint.rs +++ b/src/mint.rs @@ -58,13 +58,13 @@ impl Mint { mod tests { use super::*; use ledger::verify_slice; - use plan::{Action, Plan}; + use plan::Plan; #[test] fn test_create_events() { let mut events = Mint::new(100).create_events().into_iter(); if let Event::Transaction(tr) = events.next().unwrap() { - if let Plan::Action(Action::Pay(payment)) = tr.plan { + if let Plan::Pay(payment) = tr.plan { assert_eq!(tr.from, payment.to); } } diff --git a/src/plan.rs b/src/plan.rs index 2bd325746..168f788c0 100644 --- a/src/plan.rs +++ b/src/plan.rs @@ -25,19 +25,6 @@ impl Condition { } } -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] -pub enum Action { - Pay(Payment), -} - -impl Action { - pub fn spendable(&self) -> i64 { - match *self { - Action::Pay(ref payment) => payment.tokens, - } - } -} - #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct Payment { pub tokens: i64, @@ -46,28 +33,22 @@ pub struct Payment { #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub enum Plan { - Action(Action), - After(Condition, Action), - Race((Condition, Action), (Condition, Action)), + Pay(Payment), + After(Condition, Payment), + Race((Condition, Payment), (Condition, Payment)), } impl Plan { pub fn new_payment(tokens: i64, to: PublicKey) -> Self { - Plan::Action(Action::Pay(Payment { tokens, to })) + Plan::Pay(Payment { tokens, to }) } pub fn new_authorized_payment(from: PublicKey, tokens: i64, to: PublicKey) -> Self { - Plan::After( - Condition::Signature(from), - Action::Pay(Payment { tokens, to }), - ) + Plan::After(Condition::Signature(from), Payment { tokens, to }) } pub fn new_future_payment(dt: DateTime, tokens: i64, to: PublicKey) -> Self { - Plan::After( - Condition::Timestamp(dt), - Action::Pay(Payment { tokens, to }), - ) + Plan::After(Condition::Timestamp(dt), Payment { tokens, to }) } pub fn new_cancelable_future_payment( @@ -77,47 +58,41 @@ impl Plan { to: PublicKey, ) -> Self { Plan::Race( - ( - Condition::Timestamp(dt), - Action::Pay(Payment { tokens, to }), - ), - ( - Condition::Signature(from), - Action::Pay(Payment { tokens, to: from }), - ), + (Condition::Timestamp(dt), Payment { tokens, to }), + (Condition::Signature(from), Payment { tokens, to: from }), ) } pub fn verify(&self, spendable_tokens: i64) -> bool { match *self { - Plan::Action(ref action) => action.spendable() == spendable_tokens, - Plan::After(_, ref action) => action.spendable() == spendable_tokens, + Plan::Pay(ref payment) => payment.tokens == spendable_tokens, + Plan::After(_, ref payment) => payment.tokens == spendable_tokens, Plan::Race(ref a, ref b) => { - a.1.spendable() == spendable_tokens && b.1.spendable() == spendable_tokens + a.1.tokens == spendable_tokens && b.1.tokens == spendable_tokens } } } pub fn process_witness(&mut self, event: Witness) -> bool { - let mut new_action = None; + let mut new_payment = None; match *self { - Plan::Action(_) => return true, - Plan::After(ref cond, ref action) => { + Plan::Pay(_) => return true, + Plan::After(ref cond, ref payment) => { if cond.is_satisfied(&event) { - new_action = Some(action.clone()); + new_payment = Some(payment.clone()); } } Plan::Race(ref a, ref b) => { if a.0.is_satisfied(&event) { - new_action = Some(a.1.clone()); + new_payment = Some(a.1.clone()); } else if b.0.is_satisfied(&event) { - new_action = Some(b.1.clone()); + new_payment = Some(b.1.clone()); } } } - if let Some(action) = new_action { - mem::replace(self, Plan::Action(action)); + if let Some(payment) = new_payment { + mem::replace(self, Plan::Pay(payment)); true } else { false diff --git a/src/transaction.rs b/src/transaction.rs index 9ee7d4565..482bdddf5 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -4,7 +4,7 @@ use signature::{KeyPair, KeyPairUtil, PublicKey, Signature, SignatureUtil}; use bincode::serialize; use hash::Hash; use chrono::prelude::*; -use plan::{Action, Condition, Payment, Plan}; +use plan::{Condition, Payment, Plan}; #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct Transaction { @@ -18,7 +18,7 @@ pub struct Transaction { impl Transaction { pub fn new(from_keypair: &KeyPair, to: PublicKey, tokens: i64, last_id: Hash) -> Self { let from = from_keypair.pubkey(); - let plan = Plan::Action(Action::Pay(Payment { tokens, to })); + let plan = Plan::Pay(Payment { tokens, to }); let mut tr = Transaction { from, plan, @@ -39,14 +39,8 @@ impl Transaction { ) -> Self { let from = from_keypair.pubkey(); let plan = Plan::Race( - ( - Condition::Timestamp(dt), - Action::Pay(Payment { tokens, to }), - ), - ( - Condition::Signature(from), - Action::Pay(Payment { tokens, to: from }), - ), + (Condition::Timestamp(dt), Payment { tokens, to }), + (Condition::Signature(from), Payment { tokens, to: from }), ); let mut tr = Transaction { from, @@ -98,10 +92,10 @@ mod tests { #[test] fn test_serialize_claim() { - let plan = Plan::Action(Action::Pay(Payment { + let plan = Plan::Pay(Payment { tokens: 0, to: Default::default(), - })); + }); let claim0 = Transaction { from: Default::default(), plan, @@ -134,7 +128,7 @@ mod tests { let zero = Hash::default(); let mut tr = Transaction::new(&keypair0, pubkey1, 42, zero); tr.sign(&keypair0); - if let Plan::Action(Action::Pay(ref mut payment)) = tr.plan { + if let Plan::Pay(ref mut payment) = tr.plan { payment.to = thief_keypair.pubkey(); // <-- attack! }; assert!(!tr.verify());