Don't let users accidentally burn their funds either

This commit is contained in:
Greg Fitzgerald 2018-03-11 12:04:44 -06:00
parent aa0a184ebe
commit 45765b625a
2 changed files with 21 additions and 17 deletions

View File

@ -288,10 +288,19 @@ mod tests {
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 {
payment.asset = 2; // <-- Attack!
payment.asset = 2; // <-- attack!
}
assert_eq!(
acc.process_transaction(tr),
acc.process_transaction(tr.clone()),
Err(AccountingError::InvalidTransfer)
);
// Also, ensure all branchs of the plan spend all assets
if let Plan::Action(Action::Pay(ref mut payment)) = tr.plan {
payment.asset = 0; // <-- whoops!
}
assert_eq!(
acc.process_transaction(tr.clone()),
Err(AccountingError::InvalidTransfer)
);
}

View File

@ -6,7 +6,6 @@ use bincode::serialize;
use hash::Hash;
use chrono::prelude::*;
use std::mem;
use std::cmp;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum Condition {
@ -20,7 +19,7 @@ pub enum Action<T> {
}
impl<T: Clone> Action<T> {
pub fn max_spendable(&self) -> T {
pub fn spendable(&self) -> T {
match *self {
Action::Pay(ref payment) => payment.asset.clone(),
}
@ -40,19 +39,15 @@ pub enum Plan<T> {
Race(Box<Plan<T>>, Box<Plan<T>>),
}
impl<T: Clone + Ord> Plan<T> {
pub fn max_spendable(&self) -> T {
match *self {
Plan::Action(ref action) => action.max_spendable(),
Plan::Race(ref plan_a, ref plan_b) => {
cmp::max(plan_a.max_spendable(), plan_b.max_spendable())
}
Plan::After(_, ref action) => action.max_spendable(),
}
}
impl<T: Clone + Eq> Plan<T> {
pub fn verify(&self, spendable_assets: &T) -> bool {
self.max_spendable() <= *spendable_assets
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 action) => action.spendable() == *spendable_assets,
}
}
pub fn run_race(&mut self) -> bool {
@ -140,7 +135,7 @@ pub struct Transaction<T> {
pub sig: Signature,
}
impl<T: Serialize + Clone + Ord> Transaction<T> {
impl<T: Serialize + Clone + Eq> Transaction<T> {
pub fn new(from_keypair: &KeyPair, to: PublicKey, asset: T, last_id: Hash) -> Self {
let from = from_keypair.pubkey();
let plan = Plan::Action(Action::Pay(Payment {