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); 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); return Err(AccountingError::InsufficientFunds);
} }
@ -117,10 +117,10 @@ impl Accountant {
if let Plan::Action(Action::Pay(ref payment)) = *plan { if let Plan::Action(Action::Pay(ref payment)) = *plan {
if self.balances.contains_key(&payment.to) { if self.balances.contains_key(&payment.to) {
if let Some(x) = self.balances.get_mut(&payment.to) { if let Some(x) = self.balances.get_mut(&payment.to) {
*x += payment.asset; *x += payment.tokens;
} }
} else { } 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 !Self::is_deposit(allow_deposits, &tr.from, &tr.plan) {
if let Some(x) = self.balances.get_mut(&tr.from) { 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 bob_pubkey = KeyPair::new().pubkey();
let mut tr = Transaction::new(&alice.keypair(), bob_pubkey, 1, alice.seed()); let mut tr = Transaction::new(&alice.keypair(), bob_pubkey, 1, alice.seed());
if let Plan::Action(Action::Pay(ref mut payment)) = tr.plan { if let Plan::Action(Action::Pay(ref mut payment)) = tr.plan {
payment.asset = 2; // <-- attack! payment.tokens = 2; // <-- attack!
} }
assert_eq!( assert_eq!(
acc.process_transaction(tr.clone()), acc.process_transaction(tr.clone()),
Err(AccountingError::InvalidTransfer) 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 { if let Plan::Action(Action::Pay(ref mut payment)) = tr.plan {
payment.asset = 0; // <-- whoops! payment.tokens = 0; // <-- whoops!
} }
assert_eq!( assert_eq!(
acc.process_transaction(tr.clone()), acc.process_transaction(tr.clone()),

View File

@ -35,14 +35,14 @@ pub enum Action {
impl Action { impl Action {
pub fn spendable(&self) -> i64 { pub fn spendable(&self) -> i64 {
match *self { match *self {
Action::Pay(ref payment) => payment.asset, Action::Pay(ref payment) => payment.tokens,
} }
} }
} }
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Payment { pub struct Payment {
pub asset: i64, pub tokens: i64,
pub to: PublicKey, pub to: PublicKey,
} }
@ -54,42 +54,48 @@ pub enum Plan {
} }
impl Plan { impl Plan {
pub fn new_payment(asset: i64, to: PublicKey) -> Self { pub fn new_payment(tokens: i64, to: PublicKey) -> Self {
Plan::Action(Action::Pay(Payment { asset, to })) 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( Plan::After(
Condition::Signature(from), 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 { pub fn new_future_payment(dt: DateTime<Utc>, tokens: i64, to: PublicKey) -> Self {
Plan::After(Condition::Timestamp(dt), Action::Pay(Payment { asset, to })) Plan::After(
Condition::Timestamp(dt),
Action::Pay(Payment { tokens, to }),
)
} }
pub fn new_cancelable_future_payment( pub fn new_cancelable_future_payment(
dt: DateTime<Utc>, dt: DateTime<Utc>,
from: PublicKey, from: PublicKey,
asset: i64, tokens: i64,
to: PublicKey, to: PublicKey,
) -> Self { ) -> Self {
Plan::Race( Plan::Race(
(Condition::Timestamp(dt), Action::Pay(Payment { asset, to })), (
Condition::Timestamp(dt),
Action::Pay(Payment { tokens, to }),
),
( (
Condition::Signature(from), 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 { match *self {
Plan::Action(ref action) => action.spendable() == spendable_assets, Plan::Action(ref action) => action.spendable() == spendable_tokens,
Plan::After(_, ref action) => action.spendable() == spendable_assets, Plan::After(_, ref action) => action.spendable() == spendable_tokens,
Plan::Race(ref a, ref b) => { 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 struct Transaction {
pub from: PublicKey, pub from: PublicKey,
pub plan: Plan, pub plan: Plan,
pub asset: i64, pub tokens: i64,
pub last_id: Hash, pub last_id: Hash,
pub sig: Signature, pub sig: Signature,
} }
impl Transaction { 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 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 { let mut tr = Transaction {
from, from,
plan, plan,
asset, tokens,
last_id, last_id,
sig: Signature::default(), sig: Signature::default(),
}; };
@ -34,21 +34,24 @@ impl Transaction {
from_keypair: &KeyPair, from_keypair: &KeyPair,
to: PublicKey, to: PublicKey,
dt: DateTime<Utc>, dt: DateTime<Utc>,
asset: i64, tokens: i64,
last_id: Hash, last_id: Hash,
) -> Self { ) -> Self {
let from = from_keypair.pubkey(); let from = from_keypair.pubkey();
let plan = Plan::Race( let plan = Plan::Race(
(Condition::Timestamp(dt), Action::Pay(Payment { asset, to })), (
Condition::Timestamp(dt),
Action::Pay(Payment { tokens, to }),
),
( (
Condition::Signature(from), Condition::Signature(from),
Action::Pay(Payment { asset, to: from }), Action::Pay(Payment { tokens, to: from }),
), ),
); );
let mut tr = Transaction { let mut tr = Transaction {
from, from,
plan, plan,
asset, tokens,
last_id, last_id,
sig: Signature::default(), sig: Signature::default(),
}; };
@ -57,7 +60,7 @@ impl Transaction {
} }
fn get_sign_data(&self) -> Vec<u8> { 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) { pub fn sign(&mut self, keypair: &KeyPair) {
@ -66,7 +69,7 @@ impl Transaction {
} }
pub fn verify(&self) -> bool { 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] #[test]
fn test_serialize_claim() { fn test_serialize_claim() {
let plan = Plan::Action(Action::Pay(Payment { let plan = Plan::Action(Action::Pay(Payment {
asset: 0, tokens: 0,
to: Default::default(), to: Default::default(),
})); }));
let claim0 = Transaction { let claim0 = Transaction {
from: Default::default(), from: Default::default(),
plan, plan,
asset: 0, tokens: 0,
last_id: Default::default(), last_id: Default::default(),
sig: Default::default(), sig: Default::default(),
}; };
@ -118,7 +121,7 @@ mod tests {
let pubkey = keypair.pubkey(); let pubkey = keypair.pubkey();
let mut tr = Transaction::new(&keypair, pubkey, 42, zero); let mut tr = Transaction::new(&keypair, pubkey, 42, zero);
tr.sign(&keypair); tr.sign(&keypair);
tr.asset = 1_000_000; // <-- attack! tr.tokens = 1_000_000; // <-- attack!
assert!(!tr.verify()); assert!(!tr.verify());
} }