@ -29,6 +29,7 @@ pub struct Accountant {
|
|||||||
pub balances: HashMap<PublicKey, i64>,
|
pub balances: HashMap<PublicKey, i64>,
|
||||||
pub first_id: Hash,
|
pub first_id: Hash,
|
||||||
pub last_id: Hash,
|
pub last_id: Hash,
|
||||||
|
pub pending: HashMap<Signature, Transaction<i64>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Accountant {
|
impl Accountant {
|
||||||
@ -49,6 +50,7 @@ impl Accountant {
|
|||||||
balances: HashMap::new(),
|
balances: HashMap::new(),
|
||||||
first_id: start_hash,
|
first_id: start_hash,
|
||||||
last_id: start_hash,
|
last_id: start_hash,
|
||||||
|
pending: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// The second item in the log is a special transaction where the to and from
|
// The second item in the log is a special transaction where the to and from
|
||||||
@ -104,12 +106,20 @@ impl Accountant {
|
|||||||
return Err(AccountingError::InvalidTransferSignature);
|
return Err(AccountingError::InvalidTransferSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !tr.unless_any.is_empty() {
|
||||||
|
// TODO: Check to see if the transaction is expired.
|
||||||
|
}
|
||||||
|
|
||||||
if !Self::is_deposit(allow_deposits, &tr.from, &tr.to) {
|
if !Self::is_deposit(allow_deposits, &tr.from, &tr.to) {
|
||||||
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.asset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !tr.if_all.is_empty() {
|
||||||
|
self.pending.insert(tr.sig, tr.clone());
|
||||||
|
}
|
||||||
|
|
||||||
if self.balances.contains_key(&tr.to) {
|
if self.balances.contains_key(&tr.to) {
|
||||||
if let Some(x) = self.balances.get_mut(&tr.to) {
|
if let Some(x) = self.balances.get_mut(&tr.to) {
|
||||||
*x += tr.asset;
|
*x += tr.asset;
|
||||||
@ -121,10 +131,39 @@ impl Accountant {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn process_verified_sig(&mut self, _from: PublicKey, tx_sig: Signature) -> Result<()> {
|
||||||
|
if self.pending.contains_key(&tx_sig) {
|
||||||
|
if let Some(_tx) = self.pending.get_mut(&tx_sig) {
|
||||||
|
// Cancel:
|
||||||
|
// if Signature(from) is in unless_any, return funds to tx.from, and remove the tx from this map.
|
||||||
|
|
||||||
|
// Process Multisig:
|
||||||
|
// otherwise, if "Signature(from) is in if_all, remove it. If that causes that list
|
||||||
|
// to be empty, add the asset to to, and remove the tx from this map.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_verified_timestamp(&mut self, _from: PublicKey, _dt: DateTime<Utc>) -> Result<()> {
|
||||||
|
// TODO: Lookup pending Transaction waiting on time, signed by a whitelisted PublicKey.
|
||||||
|
|
||||||
|
// Expire:
|
||||||
|
// if a Timestamp after this DateTime is in unless_any, return funds to tx.from,
|
||||||
|
// and remove the tx from this map.
|
||||||
|
|
||||||
|
// Process postponed:
|
||||||
|
// otherwise, if "Signature(from) is in if_all, remove it. If that causes that list
|
||||||
|
// to be empty, add the asset to to, and remove the tx from this map.
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn process_verified_event(self: &mut Self, event: &Event, allow_deposits: bool) -> Result<()> {
|
fn process_verified_event(self: &mut Self, event: &Event, allow_deposits: bool) -> Result<()> {
|
||||||
match *event {
|
match *event {
|
||||||
Event::Tick => Ok(()),
|
Event::Tick => Ok(()),
|
||||||
Event::Transaction(ref tr) => self.process_verified_transaction(tr, allow_deposits),
|
Event::Transaction(ref tr) => self.process_verified_transaction(tr, allow_deposits),
|
||||||
|
Event::Signature { from, tx_sig, .. } => self.process_verified_sig(from, tx_sig),
|
||||||
|
Event::Timestamp { from, dt, .. } => self.process_verified_timestamp(from, dt),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
src/event.rs
19
src/event.rs
@ -1,7 +1,9 @@
|
|||||||
//! The `event` crate provides the data structures for log events.
|
//! The `event` crate provides the data structures for log events.
|
||||||
|
|
||||||
use signature::Signature;
|
use signature::{PublicKey, Signature, SignatureUtil};
|
||||||
use transaction::Transaction;
|
use transaction::Transaction;
|
||||||
|
use chrono::prelude::*;
|
||||||
|
use bincode::serialize;
|
||||||
|
|
||||||
/// When 'event' is Tick, the event represents a simple clock tick, and exists for the
|
/// When 'event' is Tick, the event represents a simple clock tick, and exists for the
|
||||||
/// sole purpose of improving the performance of event log verification. A tick can
|
/// sole purpose of improving the performance of event log verification. A tick can
|
||||||
@ -12,13 +14,26 @@ use transaction::Transaction;
|
|||||||
pub enum Event {
|
pub enum Event {
|
||||||
Tick,
|
Tick,
|
||||||
Transaction(Transaction<i64>),
|
Transaction(Transaction<i64>),
|
||||||
|
Signature {
|
||||||
|
from: PublicKey,
|
||||||
|
tx_sig: Signature,
|
||||||
|
sig: Signature,
|
||||||
|
},
|
||||||
|
Timestamp {
|
||||||
|
from: PublicKey,
|
||||||
|
dt: DateTime<Utc>,
|
||||||
|
sig: Signature,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Event {
|
impl Event {
|
||||||
|
// TODO: Rename this to transaction_signature().
|
||||||
pub fn get_signature(&self) -> Option<Signature> {
|
pub fn get_signature(&self) -> Option<Signature> {
|
||||||
match *self {
|
match *self {
|
||||||
Event::Tick => None,
|
Event::Tick => None,
|
||||||
Event::Transaction(ref tr) => Some(tr.sig),
|
Event::Transaction(ref tr) => Some(tr.sig),
|
||||||
|
Event::Signature { .. } => None,
|
||||||
|
Event::Timestamp { .. } => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,6 +41,8 @@ impl Event {
|
|||||||
match *self {
|
match *self {
|
||||||
Event::Tick => true,
|
Event::Tick => true,
|
||||||
Event::Transaction(ref tr) => tr.verify(),
|
Event::Transaction(ref tr) => tr.verify(),
|
||||||
|
Event::Signature { from, tx_sig, sig } => sig.verify(&from, &tx_sig),
|
||||||
|
Event::Timestamp { from, dt, sig } => sig.verify(&from, &serialize(&dt).unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,8 @@ use chrono::prelude::*;
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum Condition {
|
pub enum Condition {
|
||||||
DateTime(DateTime<Utc>),
|
Timestamp(DateTime<Utc>),
|
||||||
Cancel,
|
Signature(PublicKey),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
@ -45,11 +45,12 @@ impl<T: Serialize> Transaction<T> {
|
|||||||
asset: T,
|
asset: T,
|
||||||
last_id: Hash,
|
last_id: Hash,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let from = from_keypair.pubkey();
|
||||||
let mut tr = Transaction {
|
let mut tr = Transaction {
|
||||||
from: from_keypair.pubkey(),
|
from,
|
||||||
to,
|
to,
|
||||||
if_all: vec![Condition::DateTime(dt)],
|
if_all: vec![Condition::Timestamp(dt)],
|
||||||
unless_any: vec![Condition::Cancel],
|
unless_any: vec![Condition::Signature(from)],
|
||||||
asset,
|
asset,
|
||||||
last_id,
|
last_id,
|
||||||
sig: Signature::default(),
|
sig: Signature::default(),
|
||||||
|
Reference in New Issue
Block a user