Move spending plans to their own crate

This commit is contained in:
Greg Fitzgerald 2018-03-17 14:42:43 -06:00
parent 367c32dabe
commit e7da083c31
5 changed files with 129 additions and 122 deletions

View File

@ -5,7 +5,8 @@
use hash::Hash;
use entry::Entry;
use event::Event;
use transaction::{Action, Plan, Transaction};
use plan::{Action, Plan};
use transaction::Transaction;
use signature::{KeyPair, PublicKey, Signature};
use mint::Mint;
use historian::{reserve_signature, Historian};

View File

@ -1,6 +1,7 @@
#![cfg_attr(feature = "unstable", feature(test))]
pub mod signature;
pub mod hash;
pub mod plan;
pub mod transaction;
pub mod event;
pub mod entry;

View File

@ -58,7 +58,7 @@ impl Mint {
mod tests {
use super::*;
use log::verify_slice;
use transaction::{Action, Plan};
use plan::{Action, Plan};
#[test]
fn test_create_events() {

124
src/plan.rs Normal file
View File

@ -0,0 +1,124 @@
//! The `plan` crate provides functionality for creating spending plans.
use signature::PublicKey;
use chrono::prelude::*;
use std::mem;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Condition {
Timestamp(DateTime<Utc>),
Signature(PublicKey),
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Action<T> {
Pay(Payment<T>),
}
impl<T: Clone> Action<T> {
pub fn spendable(&self) -> T {
match *self {
Action::Pay(ref payment) => payment.asset.clone(),
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Payment<T> {
pub asset: T,
pub to: PublicKey,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Plan<T> {
Action(Action<T>),
After(Condition, Box<Plan<T>>),
Race(Box<Plan<T>>, Box<Plan<T>>),
}
impl<T: Clone + Eq> Plan<T> {
pub fn verify(&self, spendable_assets: &T) -> bool {
match *self {
Plan::Action(ref action) => action.spendable() == *spendable_assets,
Plan::Race(ref plan_a, ref plan_b) => {
plan_a.verify(spendable_assets) && plan_b.verify(spendable_assets)
}
Plan::After(_, ref plan) => plan.verify(spendable_assets),
}
}
pub fn run_race(&mut self) -> bool {
let new_plan = if let Plan::Race(ref a, ref b) = *self {
if let Plan::Action(_) = **a {
Some((**a).clone())
} else if let Plan::Action(_) = **b {
Some((**b).clone())
} else {
None
}
} else {
None
};
if let Some(plan) = new_plan {
mem::replace(self, plan);
true
} else {
false
}
}
pub fn process_verified_sig(&mut self, from: PublicKey) -> bool {
let mut new_plan = None;
match *self {
Plan::Action(_) => return true,
Plan::Race(ref mut plan_a, ref mut plan_b) => {
plan_a.process_verified_sig(from);
plan_b.process_verified_sig(from);
}
Plan::After(Condition::Signature(pubkey), ref plan) => {
if from == pubkey {
new_plan = Some((**plan).clone());
}
}
_ => (),
}
if self.run_race() {
return true;
}
if let Some(plan) = new_plan {
mem::replace(self, plan);
true
} else {
false
}
}
pub fn process_verified_timestamp(&mut self, last_time: DateTime<Utc>) -> bool {
let mut new_plan = None;
match *self {
Plan::Action(_) => return true,
Plan::Race(ref mut plan_a, ref mut plan_b) => {
plan_a.process_verified_timestamp(last_time);
plan_b.process_verified_timestamp(last_time);
}
Plan::After(Condition::Timestamp(dt), ref plan) => {
if dt <= last_time {
new_plan = Some((**plan).clone());
}
}
_ => (),
}
if self.run_race() {
return true;
}
if let Some(plan) = new_plan {
mem::replace(self, plan);
true
} else {
false
}
}
}

View File

@ -5,126 +5,7 @@ use serde::Serialize;
use bincode::serialize;
use hash::Hash;
use chrono::prelude::*;
use std::mem;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Condition {
Timestamp(DateTime<Utc>),
Signature(PublicKey),
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Action<T> {
Pay(Payment<T>),
}
impl<T: Clone> Action<T> {
pub fn spendable(&self) -> T {
match *self {
Action::Pay(ref payment) => payment.asset.clone(),
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Payment<T> {
pub asset: T,
pub to: PublicKey,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Plan<T> {
Action(Action<T>),
After(Condition, Box<Plan<T>>),
Race(Box<Plan<T>>, Box<Plan<T>>),
}
impl<T: Clone + Eq> Plan<T> {
pub fn verify(&self, spendable_assets: &T) -> bool {
match *self {
Plan::Action(ref action) => action.spendable() == *spendable_assets,
Plan::Race(ref plan_a, ref plan_b) => {
plan_a.verify(spendable_assets) && plan_b.verify(spendable_assets)
}
Plan::After(_, ref plan) => plan.verify(spendable_assets),
}
}
pub fn run_race(&mut self) -> bool {
let new_plan = if let Plan::Race(ref a, ref b) = *self {
if let Plan::Action(_) = **a {
Some((**a).clone())
} else if let Plan::Action(_) = **b {
Some((**b).clone())
} else {
None
}
} else {
None
};
if let Some(plan) = new_plan {
mem::replace(self, plan);
true
} else {
false
}
}
pub fn process_verified_sig(&mut self, from: PublicKey) -> bool {
let mut new_plan = None;
match *self {
Plan::Action(_) => return true,
Plan::Race(ref mut plan_a, ref mut plan_b) => {
plan_a.process_verified_sig(from);
plan_b.process_verified_sig(from);
}
Plan::After(Condition::Signature(pubkey), ref plan) => {
if from == pubkey {
new_plan = Some((**plan).clone());
}
}
_ => (),
}
if self.run_race() {
return true;
}
if let Some(plan) = new_plan {
mem::replace(self, plan);
true
} else {
false
}
}
pub fn process_verified_timestamp(&mut self, last_time: DateTime<Utc>) -> bool {
let mut new_plan = None;
match *self {
Plan::Action(_) => return true,
Plan::Race(ref mut plan_a, ref mut plan_b) => {
plan_a.process_verified_timestamp(last_time);
plan_b.process_verified_timestamp(last_time);
}
Plan::After(Condition::Timestamp(dt), ref plan) => {
if dt <= last_time {
new_plan = Some((**plan).clone());
}
}
_ => (),
}
if self.run_race() {
return true;
}
if let Some(plan) = new_plan {
mem::replace(self, plan);
true
} else {
false
}
}
}
use plan::{Action, Condition, Payment, Plan};
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Transaction<T> {