From aa7e3df8d658e39047c3b8c70fa6aa0850d4ad24 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 29 May 2018 13:08:59 -0600 Subject: [PATCH] Plan -> Budget Budget is now an EDSL. PaymentPlan is the interface to it. --- src/bank.rs | 4 ++-- src/mint.rs | 4 ++-- src/plan.rs | 54 +++++++++++++++++++++++----------------------- src/thin_client.rs | 4 ++-- src/transaction.rs | 18 ++++++++-------- 5 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/bank.rs b/src/bank.rs index ba19b832a4..af8fa2d061 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -9,7 +9,7 @@ use chrono::prelude::*; use entry::Entry; use hash::Hash; use mint::Mint; -use plan::{Payment, PaymentPlan, Plan, Witness}; +use plan::{Budget, Payment, PaymentPlan, Witness}; use rayon::prelude::*; use signature::{KeyPair, PublicKey, Signature}; use std::collections::hash_map::Entry::Occupied; @@ -32,7 +32,7 @@ pub type Result = result::Result; pub struct Bank { balances: RwLock>, - pending: RwLock>, + pending: RwLock>, last_ids: RwLock>)>>, time_sources: RwLock>, last_time: RwLock>, diff --git a/src/mint.rs b/src/mint.rs index 2692728ddc..3f8090ae6d 100644 --- a/src/mint.rs +++ b/src/mint.rs @@ -69,7 +69,7 @@ pub struct MintDemo { mod tests { use super::*; use ledger::Block; - use plan::Plan; + use plan::Budget; use transaction::Instruction; #[test] @@ -77,7 +77,7 @@ mod tests { let mut transactions = Mint::new(100).create_transactions().into_iter(); let tx = transactions.next().unwrap(); if let Instruction::NewContract(contract) = tx.instruction { - if let Plan::Pay(payment) = contract.plan { + if let Budget::Pay(payment) = contract.plan { assert_eq!(tx.from, payment.to); } } diff --git a/src/plan.rs b/src/plan.rs index dc669a7fe1..abc251e275 100644 --- a/src/plan.rs +++ b/src/plan.rs @@ -1,4 +1,4 @@ -//! The `plan` module provides a domain-specific language for payment plans. Users create Plan objects that +//! The `plan` module provides a domain-specific language for payment plans. Users create Budget objects that //! are given to an interpreter. The interpreter listens for `Witness` transactions, //! which it uses to reduce the payment plan. When the plan is reduced to a //! `Payment`, the payment is executed. @@ -50,26 +50,26 @@ pub trait PaymentPlan { #[repr(C)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] -pub enum Plan { +pub enum Budget { Pay(Payment), After(Condition, Payment), Race((Condition, Payment), (Condition, Payment)), } -impl Plan { +impl Budget { /// Create the simplest spending plan - one that pays `tokens` to PublicKey. pub fn new_payment(tokens: i64, to: PublicKey) -> Self { - Plan::Pay(Payment { tokens, to }) + Budget::Pay(Payment { tokens, to }) } /// Create a spending plan that pays `tokens` to `to` after being witnessed by `from`. pub fn new_authorized_payment(from: PublicKey, tokens: i64, to: PublicKey) -> Self { - Plan::After(Condition::Signature(from), Payment { tokens, to }) + Budget::After(Condition::Signature(from), Payment { tokens, to }) } /// Create a spending plan that pays `tokens` to `to` after the given DateTime. pub fn new_future_payment(dt: DateTime, tokens: i64, to: PublicKey) -> Self { - Plan::After(Condition::Timestamp(dt), Payment { tokens, to }) + Budget::After(Condition::Timestamp(dt), Payment { tokens, to }) } /// Create a spending plan that pays `tokens` to `to` after the given DateTime @@ -80,18 +80,18 @@ impl Plan { tokens: i64, to: PublicKey, ) -> Self { - Plan::Race( + Budget::Race( (Condition::Timestamp(dt), Payment { tokens, to }), (Condition::Signature(from), Payment { tokens, to: from }), ) } } -impl PaymentPlan for Plan { +impl PaymentPlan for Budget { /// Return Payment if the spending plan requires no additional Witnesses. fn final_payment(&self) -> Option { match *self { - Plan::Pay(ref payment) => Some(payment.clone()), + Budget::Pay(ref payment) => Some(payment.clone()), _ => None, } } @@ -99,10 +99,10 @@ impl PaymentPlan for Plan { /// Return true if the plan spends exactly `spendable_tokens`. fn verify(&self, spendable_tokens: i64) -> bool { match *self { - Plan::Pay(ref payment) | Plan::After(_, ref payment) => { + Budget::Pay(ref payment) | Budget::After(_, ref payment) => { payment.tokens == spendable_tokens } - Plan::Race(ref a, ref b) => { + Budget::Race(ref a, ref b) => { a.1.tokens == spendable_tokens && b.1.tokens == spendable_tokens } } @@ -112,14 +112,14 @@ impl PaymentPlan for Plan { /// If so, modify the plan in-place. fn apply_witness(&mut self, witness: &Witness) { let new_payment = match *self { - Plan::After(ref cond, ref payment) if cond.is_satisfied(witness) => Some(payment), - Plan::Race((ref cond, ref payment), _) if cond.is_satisfied(witness) => Some(payment), - Plan::Race(_, (ref cond, ref payment)) if cond.is_satisfied(witness) => Some(payment), + Budget::After(ref cond, ref payment) if cond.is_satisfied(witness) => Some(payment), + Budget::Race((ref cond, ref payment), _) if cond.is_satisfied(witness) => Some(payment), + Budget::Race(_, (ref cond, ref payment)) if cond.is_satisfied(witness) => Some(payment), _ => None, }.cloned(); if let Some(payment) = new_payment { - mem::replace(self, Plan::Pay(payment)); + mem::replace(self, Budget::Pay(payment)); } } } @@ -148,10 +148,10 @@ mod tests { let dt = Utc.ymd(2014, 11, 14).and_hms(8, 9, 10); let from = PublicKey::default(); let to = PublicKey::default(); - assert!(Plan::new_payment(42, to).verify(42)); - assert!(Plan::new_authorized_payment(from, 42, to).verify(42)); - assert!(Plan::new_future_payment(dt, 42, to).verify(42)); - assert!(Plan::new_cancelable_future_payment(dt, from, 42, to).verify(42)); + assert!(Budget::new_payment(42, to).verify(42)); + assert!(Budget::new_authorized_payment(from, 42, to).verify(42)); + assert!(Budget::new_future_payment(dt, 42, to).verify(42)); + assert!(Budget::new_cancelable_future_payment(dt, from, 42, to).verify(42)); } #[test] @@ -159,9 +159,9 @@ mod tests { let from = PublicKey::default(); let to = PublicKey::default(); - let mut plan = Plan::new_authorized_payment(from, 42, to); + let mut plan = Budget::new_authorized_payment(from, 42, to); plan.apply_witness(&Witness::Signature(from)); - assert_eq!(plan, Plan::new_payment(42, to)); + assert_eq!(plan, Budget::new_payment(42, to)); } #[test] @@ -169,9 +169,9 @@ mod tests { let dt = Utc.ymd(2014, 11, 14).and_hms(8, 9, 10); let to = PublicKey::default(); - let mut plan = Plan::new_future_payment(dt, 42, to); + let mut plan = Budget::new_future_payment(dt, 42, to); plan.apply_witness(&Witness::Timestamp(dt)); - assert_eq!(plan, Plan::new_payment(42, to)); + assert_eq!(plan, Budget::new_payment(42, to)); } #[test] @@ -180,12 +180,12 @@ mod tests { let from = PublicKey::default(); let to = PublicKey::default(); - let mut plan = Plan::new_cancelable_future_payment(dt, from, 42, to); + let mut plan = Budget::new_cancelable_future_payment(dt, from, 42, to); plan.apply_witness(&Witness::Timestamp(dt)); - assert_eq!(plan, Plan::new_payment(42, to)); + assert_eq!(plan, Budget::new_payment(42, to)); - let mut plan = Plan::new_cancelable_future_payment(dt, from, 42, to); + let mut plan = Budget::new_cancelable_future_payment(dt, from, 42, to); plan.apply_witness(&Witness::Signature(from)); - assert_eq!(plan, Plan::new_payment(42, from)); + assert_eq!(plan, Budget::new_payment(42, from)); } } diff --git a/src/thin_client.rs b/src/thin_client.rs index d8b1e4fb9b..8a5bc0db28 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -179,7 +179,7 @@ mod tests { use futures::Future; use logger; use mint::Mint; - use plan::Plan; + use plan::Budget; use server::Server; use signature::{KeyPair, KeyPairUtil}; use std::io::sink; @@ -282,7 +282,7 @@ mod tests { let mut tr2 = Transaction::new(&alice.keypair(), bob_pubkey, 501, last_id); if let Instruction::NewContract(contract) = &mut tr2.instruction { contract.tokens = 502; - contract.plan = Plan::new_payment(502, bob_pubkey); + contract.plan = Budget::new_payment(502, bob_pubkey); } let _sig = client.transfer_signed(tr2).unwrap(); diff --git a/src/transaction.rs b/src/transaction.rs index 9456f3c2c5..1dc6446af7 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -3,7 +3,7 @@ use bincode::serialize; use chrono::prelude::*; use hash::Hash; -use plan::{Condition, Payment, PaymentPlan, Plan}; +use plan::{Budget, Condition, Payment, PaymentPlan}; use signature::{KeyPair, KeyPairUtil, PublicKey, Signature, SignatureUtil}; pub const SIGNED_DATA_OFFSET: usize = 112; @@ -13,7 +13,7 @@ pub const PUB_KEY_OFFSET: usize = 80; #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct Contract { pub tokens: i64, - pub plan: Plan, + pub plan: Budget, } #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] @@ -50,7 +50,7 @@ impl Transaction { /// Create and sign a new Transaction. Used for unit-testing. pub fn new(from_keypair: &KeyPair, to: PublicKey, tokens: i64, last_id: Hash) -> Self { - let plan = Plan::Pay(Payment { tokens, to }); + let plan = Budget::Pay(Payment { tokens, to }); let instruction = Instruction::NewContract(Contract { plan, tokens }); Self::new_from_instruction(from_keypair, instruction, last_id) } @@ -76,7 +76,7 @@ impl Transaction { last_id: Hash, ) -> Self { let from = from_keypair.pubkey(); - let plan = Plan::Race( + let plan = Budget::Race( (Condition::Timestamp(dt), Payment { tokens, to }), (Condition::Signature(from), Payment { tokens, to: from }), ); @@ -162,7 +162,7 @@ mod tests { #[test] fn test_serialize_claim() { - let plan = Plan::Pay(Payment { + let plan = Budget::Pay(Payment { tokens: 0, to: Default::default(), }); @@ -186,7 +186,7 @@ mod tests { let mut tx = Transaction::new(&keypair, pubkey, 42, zero); if let Instruction::NewContract(contract) = &mut tx.instruction { contract.tokens = 1_000_000; // <-- attack, part 1! - if let Plan::Pay(ref mut payment) = contract.plan { + if let Budget::Pay(ref mut payment) = contract.plan { payment.tokens = contract.tokens; // <-- attack, part 2! } } @@ -203,7 +203,7 @@ mod tests { let zero = Hash::default(); let mut tx = Transaction::new(&keypair0, pubkey1, 42, zero); if let Instruction::NewContract(contract) = &mut tx.instruction { - if let Plan::Pay(ref mut payment) = contract.plan { + if let Budget::Pay(ref mut payment) = contract.plan { payment.to = thief_keypair.pubkey(); // <-- attack! } } @@ -227,7 +227,7 @@ mod tests { let zero = Hash::default(); let mut tx = Transaction::new(&keypair0, keypair1.pubkey(), 1, zero); if let Instruction::NewContract(contract) = &mut tx.instruction { - if let Plan::Pay(ref mut payment) = contract.plan { + if let Budget::Pay(ref mut payment) = contract.plan { payment.tokens = 2; // <-- attack! } } @@ -235,7 +235,7 @@ mod tests { // Also, ensure all branchs of the plan spend all tokens if let Instruction::NewContract(contract) = &mut tx.instruction { - if let Plan::Pay(ref mut payment) = contract.plan { + if let Budget::Pay(ref mut payment) = contract.plan { payment.tokens = 0; // <-- whoops! } }