asset -> tokens

This commit is contained in:
Greg Fitzgerald 2018-03-19 10:03:41 -06:00
parent 4f09e5d04c
commit 265f41887f
3 changed files with 44 additions and 35 deletions

View File

@ -97,7 +97,7 @@ impl Accountant {
return Err(AccountingError::InvalidTransfer);
}
if self.get_balance(&tr.from).unwrap_or(0) < tr.asset {
if self.get_balance(&tr.from).unwrap_or(0) < tr.tokens {
return Err(AccountingError::InsufficientFunds);
}
@ -117,10 +117,10 @@ impl Accountant {
if let Plan::Action(Action::Pay(ref payment)) = *plan {
if self.balances.contains_key(&payment.to) {
if let Some(x) = self.balances.get_mut(&payment.to) {
*x += payment.asset;
*x += payment.tokens;
}
} else {
self.balances.insert(payment.to, payment.asset);
self.balances.insert(payment.to, payment.tokens);
}
}
}
@ -136,7 +136,7 @@ impl Accountant {
if !Self::is_deposit(allow_deposits, &tr.from, &tr.plan) {
if let Some(x) = self.balances.get_mut(&tr.from) {
*x -= tr.asset;
*x -= tr.tokens;
}
}
@ -289,16 +289,16 @@ 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.tokens = 2; // <-- attack!
}
assert_eq!(
acc.process_transaction(tr.clone()),
Err(AccountingError::InvalidTransfer)
);
// Also, ensure all branchs of the plan spend all assets
// Also, ensure all branchs of the plan spend all tokens
if let Plan::Action(Action::Pay(ref mut payment)) = tr.plan {
payment.asset = 0; // <-- whoops!
payment.tokens = 0; // <-- whoops!
}
assert_eq!(
acc.process_transaction(tr.clone()),

View File

@ -35,14 +35,14 @@ pub enum Action {
impl Action {
pub fn spendable(&self) -> i64 {
match *self {
Action::Pay(ref payment) => payment.asset,
Action::Pay(ref payment) => payment.tokens,
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Payment {
pub asset: i64,
pub tokens: i64,
pub to: PublicKey,
}
@ -54,42 +54,48 @@ pub enum Plan {
}
impl Plan {
pub fn new_payment(asset: i64, to: PublicKey) -> Self {
Plan::Action(Action::Pay(Payment { asset, to }))
pub fn new_payment(tokens: i64, to: PublicKey) -> Self {
Plan::Action(Action::Pay(Payment { tokens, to }))
}
pub fn new_authorized_payment(from: PublicKey, asset: i64, to: PublicKey) -> Self {
pub fn new_authorized_payment(from: PublicKey, tokens: i64, to: PublicKey) -> Self {
Plan::After(
Condition::Signature(from),
Action::Pay(Payment { asset, to }),
Action::Pay(Payment { tokens, to }),
)
}
pub fn new_future_payment(dt: DateTime<Utc>, asset: i64, to: PublicKey) -> Self {
Plan::After(Condition::Timestamp(dt), Action::Pay(Payment { asset, to }))
pub fn new_future_payment(dt: DateTime<Utc>, tokens: i64, to: PublicKey) -> Self {
Plan::After(
Condition::Timestamp(dt),
Action::Pay(Payment { tokens, to }),
)
}
pub fn new_cancelable_future_payment(
dt: DateTime<Utc>,
from: PublicKey,
asset: i64,
tokens: i64,
to: PublicKey,
) -> Self {
Plan::Race(
(Condition::Timestamp(dt), Action::Pay(Payment { asset, to })),
(
Condition::Timestamp(dt),
Action::Pay(Payment { tokens, to }),
),
(
Condition::Signature(from),
Action::Pay(Payment { asset, to: from }),
Action::Pay(Payment { tokens, to: from }),
),
)
}
pub fn verify(&self, spendable_assets: i64) -> bool {
pub fn verify(&self, spendable_tokens: i64) -> bool {
match *self {
Plan::Action(ref action) => action.spendable() == spendable_assets,
Plan::After(_, ref action) => action.spendable() == spendable_assets,
Plan::Action(ref action) => action.spendable() == spendable_tokens,
Plan::After(_, ref action) => action.spendable() == spendable_tokens,
Plan::Race(ref a, ref b) => {
a.1.spendable() == spendable_assets && b.1.spendable() == spendable_assets
a.1.spendable() == spendable_tokens && b.1.spendable() == spendable_tokens
}
}
}

View File

@ -10,19 +10,19 @@ use plan::{Action, Condition, Payment, Plan};
pub struct Transaction {
pub from: PublicKey,
pub plan: Plan,
pub asset: i64,
pub tokens: i64,
pub last_id: Hash,
pub sig: Signature,
}
impl Transaction {
pub fn new(from_keypair: &KeyPair, to: PublicKey, asset: i64, last_id: Hash) -> Self {
pub fn new(from_keypair: &KeyPair, to: PublicKey, tokens: i64, last_id: Hash) -> Self {
let from = from_keypair.pubkey();
let plan = Plan::Action(Action::Pay(Payment { asset, to }));
let plan = Plan::Action(Action::Pay(Payment { tokens, to }));
let mut tr = Transaction {
from,
plan,
asset,
tokens,
last_id,
sig: Signature::default(),
};
@ -34,21 +34,24 @@ impl Transaction {
from_keypair: &KeyPair,
to: PublicKey,
dt: DateTime<Utc>,
asset: i64,
tokens: i64,
last_id: Hash,
) -> Self {
let from = from_keypair.pubkey();
let plan = Plan::Race(
(Condition::Timestamp(dt), Action::Pay(Payment { asset, to })),
(
Condition::Timestamp(dt),
Action::Pay(Payment { tokens, to }),
),
(
Condition::Signature(from),
Action::Pay(Payment { asset, to: from }),
Action::Pay(Payment { tokens, to: from }),
),
);
let mut tr = Transaction {
from,
plan,
asset,
tokens,
last_id,
sig: Signature::default(),
};
@ -57,7 +60,7 @@ impl Transaction {
}
fn get_sign_data(&self) -> Vec<u8> {
serialize(&(&self.from, &self.plan, &self.asset, &self.last_id)).unwrap()
serialize(&(&self.from, &self.plan, &self.tokens, &self.last_id)).unwrap()
}
pub fn sign(&mut self, keypair: &KeyPair) {
@ -66,7 +69,7 @@ impl Transaction {
}
pub fn verify(&self) -> bool {
self.sig.verify(&self.from, &self.get_sign_data()) && self.plan.verify(self.asset)
self.sig.verify(&self.from, &self.get_sign_data()) && self.plan.verify(self.tokens)
}
}
@ -96,13 +99,13 @@ mod tests {
#[test]
fn test_serialize_claim() {
let plan = Plan::Action(Action::Pay(Payment {
asset: 0,
tokens: 0,
to: Default::default(),
}));
let claim0 = Transaction {
from: Default::default(),
plan,
asset: 0,
tokens: 0,
last_id: Default::default(),
sig: Default::default(),
};
@ -118,7 +121,7 @@ mod tests {
let pubkey = keypair.pubkey();
let mut tr = Transaction::new(&keypair, pubkey, 42, zero);
tr.sign(&keypair);
tr.asset = 1_000_000; // <-- attack!
tr.tokens = 1_000_000; // <-- attack!
assert!(!tr.verify());
}