diff --git a/teos/src/dbm.rs b/teos/src/dbm.rs index 4a53abda..16c3f396 100644 --- a/teos/src/dbm.rs +++ b/teos/src/dbm.rs @@ -19,9 +19,9 @@ use teos_common::constants::ENCRYPTED_BLOB_MAX_SIZE; use teos_common::dbm::{DatabaseConnection, DatabaseManager, Error}; use teos_common::UserId; -use crate::extended_appointment::{ExtendedAppointment, UUID}; +use crate::extended_appointment::{AppointmentSummary, ExtendedAppointment, UUID}; use crate::gatekeeper::UserInfo; -use crate::responder::{ConfirmationStatus, TransactionTracker}; +use crate::responder::{ConfirmationStatus, TrackerSummary, TransactionTracker}; const TABLES: [&str; 5] = [ "CREATE TABLE IF NOT EXISTS users ( @@ -305,6 +305,34 @@ impl DBM { .ok() } + /// Loads all [AppointmentSummary]s from that database. + pub(crate) fn load_appointment_summaries(&self) -> HashMap { + let mut summaries = HashMap::new(); + + let mut stmt = self + .connection + .prepare( + "SELECT a.UUID, a.locator, a.user_id + FROM appointments as a LEFT JOIN trackers as t ON a.UUID=t.UUID WHERE t.UUID IS NULL", + ) + .unwrap(); + let mut rows = stmt.query([]).unwrap(); + + while let Ok(Some(row)) = rows.next() { + let raw_uuid: Vec = row.get(0).unwrap(); + let raw_locator: Vec = row.get(1).unwrap(); + let raw_userid: Vec = row.get(2).unwrap(); + summaries.insert( + UUID::from_slice(&raw_uuid).unwrap(), + AppointmentSummary::new( + Locator::from_slice(&raw_locator).unwrap(), + UserId::from_slice(&raw_userid).unwrap(), + ), + ); + } + summaries + } + /// Loads appointments from the database. If a locator is given, this method loads only the appointments /// matching this locator. If no locator is given, all the appointments in the database would be returned. pub(crate) fn load_appointments( @@ -481,6 +509,39 @@ impl DBM { .ok() } + /// Loads all [TrackerSummary]s from that database. + pub(crate) fn load_tracker_summaries(&self) -> HashMap { + let mut summaries = HashMap::new(); + + let mut stmt = self + .connection + .prepare( + "SELECT t.UUID, t.penalty_tx, t.height, t.confirmed, a.user_id + FROM trackers as t INNER JOIN appointments as a ON t.UUID=a.UUID", + ) + .unwrap(); + let mut rows = stmt.query([]).unwrap(); + + while let Ok(Some(row)) = rows.next() { + let raw_uuid: Vec = row.get(0).unwrap(); + let raw_penalty_tx: Vec = row.get(1).unwrap(); + let height: u32 = row.get(2).unwrap(); + let confirmed: bool = row.get(3).unwrap(); + let raw_userid: Vec = row.get(4).unwrap(); + summaries.insert( + UUID::from_slice(&raw_uuid).unwrap(), + TrackerSummary::new( + UserId::from_slice(&raw_userid).unwrap(), + consensus::deserialize::(&raw_penalty_tx) + .unwrap() + .txid(), + ConfirmationStatus::from_db_data(height, confirmed), + ), + ); + } + summaries + } + /// Loads trackers from the database. If a locator is given, this method loads only the trackers /// matching this locator. If no locator is given, all the trackers in the database would be returned. pub(crate) fn load_trackers( diff --git a/teos/src/extended_appointment.rs b/teos/src/extended_appointment.rs index 88920de0..32cc0b94 100644 --- a/teos/src/extended_appointment.rs +++ b/teos/src/extended_appointment.rs @@ -72,6 +72,12 @@ pub(crate) struct AppointmentSummary { pub user_id: UserId, } +impl AppointmentSummary { + pub fn new(locator: Locator, user_id: UserId) -> Self { + Self { locator, user_id } + } +} + impl ExtendedAppointment { /// Create a new [ExtendedAppointment]. pub fn new( diff --git a/teos/src/responder.rs b/teos/src/responder.rs index 9ffebda0..3ace73e4 100644 --- a/teos/src/responder.rs +++ b/teos/src/responder.rs @@ -83,6 +83,16 @@ pub(crate) struct TrackerSummary { status: ConfirmationStatus, } +impl TrackerSummary { + pub fn new(user_id: UserId, penalty_txid: Txid, status: ConfirmationStatus) -> Self { + Self { + user_id, + penalty_txid, + status, + } + } +} + /// Structure to keep track of triggered appointments. /// /// It is analogous to [ExtendedAppointment](crate::extended_appointment::ExtendedAppointment) for the [`Watcher`](crate::watcher::Watcher). @@ -163,14 +173,13 @@ impl Responder { let mut trackers = HashMap::new(); let mut tx_tracker_map: HashMap> = HashMap::new(); - for (uuid, tracker) in dbm.lock().unwrap().load_trackers(None) { - trackers.insert(uuid, tracker.get_summary()); - - if let Some(map) = tx_tracker_map.get_mut(&tracker.penalty_tx.txid()) { + for (uuid, summary) in dbm.lock().unwrap().load_tracker_summaries() { + if let Some(map) = tx_tracker_map.get_mut(&summary.penalty_txid) { map.insert(uuid); } else { - tx_tracker_map.insert(tracker.penalty_tx.txid(), HashSet::from_iter(vec![uuid])); + tx_tracker_map.insert(summary.penalty_txid, HashSet::from_iter(vec![uuid])); } + trackers.insert(uuid, summary); } Responder { diff --git a/teos/src/watcher.rs b/teos/src/watcher.rs index ec2e7da5..8a6f0582 100644 --- a/teos/src/watcher.rs +++ b/teos/src/watcher.rs @@ -141,14 +141,13 @@ impl Watcher { ) -> Self { let mut appointments = HashMap::new(); let mut locator_uuid_map: HashMap> = HashMap::new(); - for (uuid, appointment) in dbm.lock().unwrap().load_appointments(None) { - appointments.insert(uuid, appointment.get_summary()); - - if let Some(map) = locator_uuid_map.get_mut(&appointment.locator()) { + for (uuid, summary) in dbm.lock().unwrap().load_appointment_summaries() { + if let Some(map) = locator_uuid_map.get_mut(&summary.locator) { map.insert(uuid); } else { - locator_uuid_map.insert(appointment.locator(), HashSet::from_iter(vec![uuid])); + locator_uuid_map.insert(summary.locator, HashSet::from_iter(vec![uuid])); } + appointments.insert(uuid, summary); } Watcher {