Move spending endpoints into expressions
This commit is contained in:
parent
7a0bc7d888
commit
8c40d1bd72
|
@ -109,12 +109,13 @@ impl Accountant {
|
|||
|
||||
/// Commit funds to the 'to' party.
|
||||
fn complete_transaction(self: &mut Self, tr: &Transaction<i64>) {
|
||||
if self.balances.contains_key(&tr.plan.to) {
|
||||
if let Some(x) = self.balances.get_mut(&tr.plan.to) {
|
||||
let to = tr.plan.to();
|
||||
if self.balances.contains_key(&to) {
|
||||
if let Some(x) = self.balances.get_mut(&to) {
|
||||
*x += tr.asset;
|
||||
}
|
||||
} else {
|
||||
self.balances.insert(tr.plan.to, tr.asset);
|
||||
self.balances.insert(to, tr.asset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,17 +150,17 @@ impl Accountant {
|
|||
return Err(AccountingError::InvalidTransferSignature);
|
||||
}
|
||||
|
||||
if !tr.plan.unless_any.is_empty() {
|
||||
if !tr.plan.unless_any.0.is_empty() {
|
||||
// TODO: Check to see if the transaction is expired.
|
||||
}
|
||||
|
||||
if !Self::is_deposit(allow_deposits, &tr.from, &tr.plan.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.plan.if_all) {
|
||||
if !self.all_satisfied(&tr.plan.if_all.0) {
|
||||
self.pending.insert(tr.sig, tr.clone());
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -175,7 +176,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.plan.unless_any {
|
||||
for cond in &tr.plan.unless_any.0 {
|
||||
if let Condition::Signature(pubkey) = *cond {
|
||||
if from == pubkey {
|
||||
cancel = true;
|
||||
|
@ -220,17 +221,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.plan.if_all {
|
||||
for cond in &tr.plan.if_all.0 {
|
||||
if let Condition::Timestamp(dt) = *cond {
|
||||
if self.last_time >= dt {
|
||||
if tr.plan.if_all.len() == 1 {
|
||||
if tr.plan.if_all.0.len() == 1 {
|
||||
completed.push(*key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Add this in once we start removing constraints
|
||||
//if tr.plan.if_all.is_empty() {
|
||||
//if tr.plan.if_all.0.is_empty() {
|
||||
// // TODO: Remove tr from pending
|
||||
// self.complete_transaction(tr);
|
||||
//}
|
||||
|
|
|
@ -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.plan.to);
|
||||
assert_eq!(tr.from, tr.plan.to());
|
||||
}
|
||||
assert_eq!(events.next(), None);
|
||||
}
|
||||
|
|
|
@ -13,30 +13,59 @@ pub enum Condition {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct SpendingPlan {
|
||||
pub enum Action<T> {
|
||||
Pay(Payment<T>),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Payment<T> {
|
||||
pub asset: T,
|
||||
pub to: PublicKey,
|
||||
pub if_all: Vec<Condition>,
|
||||
pub unless_any: Vec<Condition>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct SpendingPlan<T> {
|
||||
pub if_all: (Vec<Condition>, Action<T>),
|
||||
pub unless_any: (Vec<Condition>, Action<T>),
|
||||
}
|
||||
|
||||
impl<T> SpendingPlan<T> {
|
||||
pub fn to(&self) -> PublicKey {
|
||||
let Action::Pay(ref payment) = self.if_all.1;
|
||||
payment.to
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Transaction<T> {
|
||||
pub from: PublicKey,
|
||||
pub plan: SpendingPlan,
|
||||
pub plan: SpendingPlan<T>,
|
||||
pub asset: T,
|
||||
pub last_id: Hash,
|
||||
pub sig: Signature,
|
||||
}
|
||||
|
||||
impl<T: Serialize> Transaction<T> {
|
||||
impl<T: Serialize + Clone> Transaction<T> {
|
||||
pub fn new(from_keypair: &KeyPair, to: PublicKey, asset: T, last_id: Hash) -> Self {
|
||||
let from = from_keypair.pubkey();
|
||||
let plan = SpendingPlan {
|
||||
to,
|
||||
if_all: vec![],
|
||||
unless_any: vec![],
|
||||
if_all: (
|
||||
vec![],
|
||||
Action::Pay(Payment {
|
||||
asset: asset.clone(),
|
||||
to,
|
||||
}),
|
||||
),
|
||||
unless_any: (
|
||||
vec![],
|
||||
Action::Pay(Payment {
|
||||
asset: asset.clone(),
|
||||
to: from,
|
||||
}),
|
||||
),
|
||||
};
|
||||
let mut tr = Transaction {
|
||||
from: from_keypair.pubkey(),
|
||||
from,
|
||||
plan,
|
||||
asset,
|
||||
last_id,
|
||||
|
@ -55,9 +84,20 @@ impl<T: Serialize> Transaction<T> {
|
|||
) -> Self {
|
||||
let from = from_keypair.pubkey();
|
||||
let plan = SpendingPlan {
|
||||
to,
|
||||
if_all: vec![Condition::Timestamp(dt)],
|
||||
unless_any: vec![Condition::Signature(from)],
|
||||
if_all: (
|
||||
vec![Condition::Timestamp(dt)],
|
||||
Action::Pay(Payment {
|
||||
asset: asset.clone(),
|
||||
to,
|
||||
}),
|
||||
),
|
||||
unless_any: (
|
||||
vec![Condition::Signature(from)],
|
||||
Action::Pay(Payment {
|
||||
asset: asset.clone(),
|
||||
to: from,
|
||||
}),
|
||||
),
|
||||
};
|
||||
let mut tr = Transaction {
|
||||
from,
|
||||
|
@ -74,7 +114,6 @@ impl<T: Serialize> Transaction<T> {
|
|||
let plan = &self.plan;
|
||||
serialize(&(
|
||||
&self.from,
|
||||
&plan.to,
|
||||
&plan.if_all,
|
||||
&plan.unless_any,
|
||||
&self.asset,
|
||||
|
@ -121,9 +160,20 @@ mod tests {
|
|||
#[test]
|
||||
fn test_serialize_claim() {
|
||||
let plan = SpendingPlan {
|
||||
to: Default::default(),
|
||||
if_all: Default::default(),
|
||||
unless_any: Default::default(),
|
||||
if_all: (
|
||||
Default::default(),
|
||||
Action::Pay(Payment {
|
||||
asset: 0,
|
||||
to: Default::default(),
|
||||
}),
|
||||
),
|
||||
unless_any: (
|
||||
Default::default(),
|
||||
Action::Pay(Payment {
|
||||
asset: 0,
|
||||
to: Default::default(),
|
||||
}),
|
||||
),
|
||||
};
|
||||
let claim0 = Transaction {
|
||||
from: Default::default(),
|
||||
|
@ -155,9 +205,13 @@ mod tests {
|
|||
let thief_keypair = KeyPair::new();
|
||||
let pubkey1 = keypair1.pubkey();
|
||||
let zero = Hash::default();
|
||||
let mut tr = Transaction::new(&keypair0, pubkey1, hash(b"hello, world"), zero);
|
||||
let asset = hash(b"hello, world");
|
||||
let mut tr = Transaction::new(&keypair0, pubkey1, asset, zero);
|
||||
tr.sign(&keypair0);
|
||||
tr.plan.to = thief_keypair.pubkey(); // <-- attack!
|
||||
tr.plan.if_all.1 = Action::Pay(Payment {
|
||||
asset,
|
||||
to: thief_keypair.pubkey(),
|
||||
}); // <-- attack!
|
||||
assert!(!tr.verify());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue