Revoke API access to first_id
This commit is contained in:
parent
e683c34a89
commit
46e8c09bd8
|
@ -15,7 +15,7 @@ use signature::{KeyPair, PublicKey, Signature};
|
|||
use std::collections::hash_map::Entry::Occupied;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::result;
|
||||
use std::sync::mpsc::SendError;
|
||||
use std::sync::mpsc::{Receiver, SendError};
|
||||
use transaction::Transaction;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
|
@ -36,9 +36,8 @@ fn complete_transaction(balances: &mut HashMap<PublicKey, i64>, plan: &Plan) {
|
|||
}
|
||||
|
||||
pub struct Accountant {
|
||||
pub historian: Historian,
|
||||
pub balances: HashMap<PublicKey, i64>,
|
||||
pub first_id: Hash,
|
||||
historian: Historian,
|
||||
balances: HashMap<PublicKey, i64>,
|
||||
pending: HashMap<Signature, Plan>,
|
||||
time_sources: HashSet<PublicKey>,
|
||||
last_time: DateTime<Utc>,
|
||||
|
@ -46,7 +45,7 @@ pub struct Accountant {
|
|||
|
||||
impl Accountant {
|
||||
/// Create an Accountant using an existing ledger.
|
||||
pub fn new_from_entries<I>(entries: I, ms_per_tick: Option<u64>) -> Self
|
||||
pub fn new_from_entries<I>(entries: I, ms_per_tick: Option<u64>) -> (Self, Hash)
|
||||
where
|
||||
I: IntoIterator<Item = Entry>,
|
||||
{
|
||||
|
@ -61,7 +60,6 @@ impl Accountant {
|
|||
let mut acc = Accountant {
|
||||
historian: hist,
|
||||
balances: HashMap::new(),
|
||||
first_id: start_hash,
|
||||
pending: HashMap::new(),
|
||||
time_sources: HashSet::new(),
|
||||
last_time: Utc.timestamp(0, 0),
|
||||
|
@ -73,17 +71,19 @@ impl Accountant {
|
|||
let entry1 = entries.next().unwrap();
|
||||
acc.process_verified_event(&entry1.events[0], true).unwrap();
|
||||
|
||||
let mut last_id = entry1.id;
|
||||
for entry in entries {
|
||||
last_id = entry.id;
|
||||
for event in entry.events {
|
||||
acc.process_verified_event(&event, false).unwrap();
|
||||
}
|
||||
}
|
||||
acc
|
||||
(acc, last_id)
|
||||
}
|
||||
|
||||
/// Create an Accountant with only a Mint. Typically used by unit tests.
|
||||
pub fn new(mint: &Mint, ms_per_tick: Option<u64>) -> Self {
|
||||
Self::new_from_entries(mint.create_entries(), ms_per_tick)
|
||||
Self::new_from_entries(mint.create_entries(), ms_per_tick).0
|
||||
}
|
||||
|
||||
fn is_deposit(allow_deposits: bool, from: &PublicKey, plan: &Plan) -> bool {
|
||||
|
@ -94,6 +94,10 @@ impl Accountant {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn receiver(&self) -> &Receiver<Entry> {
|
||||
&self.historian.receiver
|
||||
}
|
||||
|
||||
/// Process and log the given Transaction.
|
||||
pub fn log_verified_transaction(&mut self, tr: Transaction) -> Result<()> {
|
||||
if self.get_balance(&tr.from).unwrap_or(0) < tr.tokens {
|
||||
|
|
|
@ -22,8 +22,8 @@ use transaction::Transaction;
|
|||
use rayon::prelude::*;
|
||||
|
||||
pub struct AccountantSkel<W: Write + Send + 'static> {
|
||||
pub acc: Accountant,
|
||||
pub last_id: Hash,
|
||||
acc: Accountant,
|
||||
last_id: Hash,
|
||||
writer: W,
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ pub struct AccountantSkel<W: Write + Send + 'static> {
|
|||
pub enum Request {
|
||||
Transaction(Transaction),
|
||||
GetBalance { key: PublicKey },
|
||||
GetId { is_last: bool },
|
||||
GetLastId,
|
||||
}
|
||||
|
||||
impl Request {
|
||||
|
@ -54,23 +54,22 @@ fn filter_valid_requests(reqs: Vec<(Request, SocketAddr)>) -> Vec<(Request, Sock
|
|||
pub enum Response {
|
||||
Balance { key: PublicKey, val: Option<i64> },
|
||||
Entries { entries: Vec<Entry> },
|
||||
Id { id: Hash, is_last: bool },
|
||||
LastId { id: Hash },
|
||||
}
|
||||
|
||||
impl<W: Write + Send + 'static> AccountantSkel<W> {
|
||||
/// Create a new AccountantSkel that wraps the given Accountant.
|
||||
pub fn new(acc: Accountant, w: W) -> Self {
|
||||
let last_id = acc.first_id;
|
||||
pub fn new(acc: Accountant, last_id: Hash, writer: W) -> Self {
|
||||
AccountantSkel {
|
||||
acc,
|
||||
last_id,
|
||||
writer: w,
|
||||
writer,
|
||||
}
|
||||
}
|
||||
|
||||
/// Process any Entry items that have been published by the Historian.
|
||||
pub fn sync(&mut self) -> Hash {
|
||||
while let Ok(entry) = self.acc.historian.receiver.try_recv() {
|
||||
while let Ok(entry) = self.acc.receiver().try_recv() {
|
||||
self.last_id = entry.id;
|
||||
writeln!(self.writer, "{}", serde_json::to_string(&entry).unwrap()).unwrap();
|
||||
}
|
||||
|
@ -90,14 +89,7 @@ impl<W: Write + Send + 'static> AccountantSkel<W> {
|
|||
let val = self.acc.get_balance(&key);
|
||||
Some(Response::Balance { key, val })
|
||||
}
|
||||
Request::GetId { is_last } => Some(Response::Id {
|
||||
id: if is_last {
|
||||
self.sync()
|
||||
} else {
|
||||
self.acc.first_id
|
||||
},
|
||||
is_last,
|
||||
}),
|
||||
Request::GetLastId => Some(Response::LastId { id: self.sync() }),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,26 +65,21 @@ impl AccountantStub {
|
|||
Ok(None)
|
||||
}
|
||||
|
||||
/// Request the first or last Entry ID from the server.
|
||||
fn get_id(&self, is_last: bool) -> io::Result<Hash> {
|
||||
let req = Request::GetId { is_last };
|
||||
let data = serialize(&req).expect("serialize GetId");
|
||||
self.socket.send_to(&data, &self.addr)?;
|
||||
let mut buf = vec![0u8; 1024];
|
||||
self.socket.recv_from(&mut buf)?;
|
||||
let resp = deserialize(&buf).expect("deserialize Id");
|
||||
if let Response::Id { id, .. } = resp {
|
||||
return Ok(id);
|
||||
}
|
||||
Ok(Default::default())
|
||||
}
|
||||
|
||||
/// Request the last Entry ID from the server. This method blocks
|
||||
/// until the server sends a response. At the time of this writing,
|
||||
/// it also has the side-effect of causing the server to log any
|
||||
/// entries that have been published by the Historian.
|
||||
pub fn get_last_id(&self) -> io::Result<Hash> {
|
||||
self.get_id(true)
|
||||
let req = Request::GetLastId;
|
||||
let data = serialize(&req).expect("serialize GetId");
|
||||
self.socket.send_to(&data, &self.addr)?;
|
||||
let mut buf = vec![0u8; 1024];
|
||||
self.socket.recv_from(&mut buf)?;
|
||||
let resp = deserialize(&buf).expect("deserialize Id");
|
||||
if let Response::LastId { id } = resp {
|
||||
return Ok(id);
|
||||
}
|
||||
Ok(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +105,7 @@ mod tests {
|
|||
let acc = Accountant::new(&alice, Some(30));
|
||||
let bob_pubkey = KeyPair::new().pubkey();
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let acc = Arc::new(Mutex::new(AccountantSkel::new(acc, sink())));
|
||||
let acc = Arc::new(Mutex::new(AccountantSkel::new(acc, alice.seed(), sink())));
|
||||
let _threads = AccountantSkel::serve(acc, addr, exit.clone()).unwrap();
|
||||
sleep(Duration::from_millis(300));
|
||||
|
||||
|
|
|
@ -14,9 +14,9 @@ fn main() {
|
|||
.lock()
|
||||
.lines()
|
||||
.map(|line| serde_json::from_str(&line.unwrap()).unwrap());
|
||||
let acc = Accountant::new_from_entries(entries, Some(1000));
|
||||
let (acc, last_id) = Accountant::new_from_entries(entries, Some(1000));
|
||||
let exit = Arc::new(AtomicBool::new(false));
|
||||
let skel = Arc::new(Mutex::new(AccountantSkel::new(acc, stdout())));
|
||||
let skel = Arc::new(Mutex::new(AccountantSkel::new(acc, last_id, stdout())));
|
||||
eprintln!("Listening on {}", addr);
|
||||
let threads = AccountantSkel::serve(skel, addr, exit.clone()).unwrap();
|
||||
for t in threads {
|
||||
|
|
|
@ -34,11 +34,11 @@ pub struct Recorder {
|
|||
}
|
||||
|
||||
impl Recorder {
|
||||
pub fn new(receiver: Receiver<Signal>, sender: SyncSender<Entry>, start_hash: Hash) -> Self {
|
||||
pub fn new(receiver: Receiver<Signal>, sender: SyncSender<Entry>, last_hash: Hash) -> Self {
|
||||
Recorder {
|
||||
receiver,
|
||||
sender,
|
||||
last_hash: start_hash,
|
||||
last_hash,
|
||||
events: vec![],
|
||||
num_hashes: 0,
|
||||
num_ticks: 0,
|
||||
|
|
Loading…
Reference in New Issue