Move spending plans to their own crate
This commit is contained in:
@ -5,7 +5,8 @@
|
|||||||
use hash::Hash;
|
use hash::Hash;
|
||||||
use entry::Entry;
|
use entry::Entry;
|
||||||
use event::Event;
|
use event::Event;
|
||||||
use transaction::{Action, Plan, Transaction};
|
use plan::{Action, Plan};
|
||||||
|
use transaction::Transaction;
|
||||||
use signature::{KeyPair, PublicKey, Signature};
|
use signature::{KeyPair, PublicKey, Signature};
|
||||||
use mint::Mint;
|
use mint::Mint;
|
||||||
use historian::{reserve_signature, Historian};
|
use historian::{reserve_signature, Historian};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![cfg_attr(feature = "unstable", feature(test))]
|
#![cfg_attr(feature = "unstable", feature(test))]
|
||||||
pub mod signature;
|
pub mod signature;
|
||||||
pub mod hash;
|
pub mod hash;
|
||||||
|
pub mod plan;
|
||||||
pub mod transaction;
|
pub mod transaction;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod entry;
|
pub mod entry;
|
||||||
|
@ -58,7 +58,7 @@ impl Mint {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use log::verify_slice;
|
use log::verify_slice;
|
||||||
use transaction::{Action, Plan};
|
use plan::{Action, Plan};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create_events() {
|
fn test_create_events() {
|
||||||
|
124
src/plan.rs
Normal file
124
src/plan.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,126 +5,7 @@ use serde::Serialize;
|
|||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use hash::Hash;
|
use hash::Hash;
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use std::mem;
|
use plan::{Action, Condition, Payment, Plan};
|
||||||
|
|
||||||
#[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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct Transaction<T> {
|
pub struct Transaction<T> {
|
||||||
|
Reference in New Issue
Block a user