diff --git a/teos/src/chain_monitor.rs b/teos/src/chain_monitor.rs index 0119267..3553401 100644 --- a/teos/src/chain_monitor.rs +++ b/teos/src/chain_monitor.rs @@ -264,10 +264,7 @@ mod tests { // If a new (worse, just one) block gets mined, nothing gets connected nor disconnected cm.poll_best_tip().await; assert_eq!(cm.last_known_block_header, best_tip); - assert!(matches!( - cm.dbm.lock().unwrap().load_last_known_block(), - Err { .. } - )); + assert!(cm.dbm.lock().unwrap().load_last_known_block().is_none()); assert!(listener.connected_blocks.borrow().is_empty()); assert!(listener.disconnected_blocks.borrow().is_empty()); } diff --git a/teos/src/dbm.rs b/teos/src/dbm.rs index af27214..4a53abd 100644 --- a/teos/src/dbm.rs +++ b/teos/src/dbm.rs @@ -274,7 +274,7 @@ impl DBM { } /// Loads an [Appointment] from the database. - pub(crate) fn load_appointment(&self, uuid: UUID) -> Result { + pub(crate) fn load_appointment(&self, uuid: UUID) -> Option { let key = uuid.to_vec(); let mut stmt = self .connection @@ -302,7 +302,7 @@ impl DBM { start_block, )) }) - .map_err(|_| Error::NotFound) + .ok() } /// Loads appointments from the database. If a locator is given, this method loads only the appointments @@ -406,7 +406,7 @@ impl DBM { } /// Loads the locator associated to a given UUID - pub(crate) fn load_locator(&self, uuid: UUID) -> Result { + pub(crate) fn load_locator(&self, uuid: UUID) -> Option { let mut stmt = self .connection .prepare("SELECT locator FROM appointments WHERE UUID=(?)") @@ -416,7 +416,7 @@ impl DBM { let raw_locator: Vec = row.get(0).unwrap(); Ok(Locator::from_slice(&raw_locator).unwrap()) }) - .map_err(|_| Error::NotFound) + .ok() } /// Stores a [TransactionTracker] into the database. @@ -451,7 +451,7 @@ impl DBM { } /// Loads a [TransactionTracker] from the database. - pub(crate) fn load_tracker(&self, uuid: UUID) -> Result { + pub(crate) fn load_tracker(&self, uuid: UUID) -> Option { let key = uuid.to_vec(); let mut stmt = self .connection.prepare( @@ -478,7 +478,7 @@ impl DBM { user_id, }) }) - .map_err(|_| Error::NotFound) + .ok() } /// Loads trackers from the database. If a locator is given, this method loads only the trackers @@ -537,7 +537,7 @@ impl DBM { } /// Loads the last known block from the database. - pub fn load_last_known_block(&self) -> Result { + pub fn load_last_known_block(&self) -> Option { let mut stmt = self .connection .prepare("SELECT block_hash FROM last_known_block WHERE id=0") @@ -547,7 +547,7 @@ impl DBM { let raw_hash: Vec = row.get(0).unwrap(); Ok(BlockHash::from_slice(&raw_hash).unwrap()) }) - .map_err(|_| Error::NotFound) + .ok() } /// Stores the tower secret key into the database. @@ -562,7 +562,7 @@ impl DBM { /// /// Loads the key with higher id from the database. Old keys are not overwritten just in case a recovery is needed, /// but they are not accessible from the API either. - pub fn load_tower_key(&self) -> Result { + pub fn load_tower_key(&self) -> Option { let mut stmt = self .connection .prepare( @@ -574,7 +574,7 @@ impl DBM { let sk: String = row.get(0).unwrap(); Ok(SecretKey::from_str(&sk).unwrap()) }) - .map_err(|_| Error::NotFound) + .ok() } } @@ -602,7 +602,7 @@ mod tests { Ok(dbm) } - pub(crate) fn load_user(&self, user_id: UserId) -> Result { + pub(crate) fn load_user(&self, user_id: UserId) -> Option { let key = user_id.to_vec(); let mut stmt = self .connection @@ -611,21 +611,18 @@ mod tests { FROM users WHERE user_id=(?)", ) .unwrap(); - let user = stmt - .query_row([&key], |row| { - let slots = row.get(1).unwrap(); - let start = row.get(2).unwrap(); - let expiry = row.get(3).unwrap(); - Ok(UserInfo::with_appointments( - slots, - start, - expiry, - self.load_user_appointments(user_id), - )) - }) - .map_err(|_| Error::NotFound)?; - - Ok(user) + stmt.query_row([&key], |row| { + let slots = row.get(1).unwrap(); + let start = row.get(2).unwrap(); + let expiry = row.get(3).unwrap(); + Ok(UserInfo::with_appointments( + slots, + start, + expiry, + self.load_user_appointments(user_id), + )) + }) + .ok() } } @@ -680,7 +677,7 @@ mod tests { let dbm = DBM::in_memory().unwrap(); let user_id = get_random_user_id(); - assert!(matches!(dbm.load_user(user_id), Err(Error::NotFound))); + assert!(dbm.load_user(user_id).is_none()); } #[test] @@ -779,11 +776,8 @@ mod tests { )); dbm.batch_remove_users(&HashSet::from_iter(vec![appointment.user_id])); - assert!(matches!( - dbm.load_user(appointment.user_id), - Err(Error::NotFound) - )); - assert!(matches!(dbm.load_appointment(uuid), Err(Error::NotFound))); + assert!(dbm.load_user(appointment.user_id).is_none()); + assert!(dbm.load_appointment(uuid).is_none()); // Appointment + Tracker dbm.store_user(appointment.user_id, &info).unwrap(); @@ -794,12 +788,9 @@ mod tests { assert!(matches!(dbm.store_tracker(uuid, &tracker), Ok { .. })); dbm.batch_remove_users(&HashSet::from_iter(vec![appointment.user_id])); - assert!(matches!( - dbm.load_user(appointment.user_id), - Err(Error::NotFound) - )); - assert!(matches!(dbm.load_appointment(uuid), Err(Error::NotFound))); - assert!(matches!(dbm.load_tracker(uuid), Err(Error::NotFound))); + assert!(dbm.load_user(appointment.user_id).is_none()); + assert!(dbm.load_appointment(uuid).is_none()); + assert!(dbm.load_tracker(uuid).is_none()); } #[test] @@ -846,7 +837,7 @@ mod tests { dbm.store_appointment(uuid, &appointment), Err(Error::MissingForeignKey) )); - assert!(matches!(dbm.load_tracker(uuid), Err(Error::NotFound))); + assert!((dbm.load_tracker(uuid).is_none())); } #[test] @@ -854,7 +845,7 @@ mod tests { let dbm = DBM::in_memory().unwrap(); let uuid = generate_uuid(); - assert!(matches!(dbm.load_appointment(uuid), Err(Error::NotFound))); + assert!(dbm.load_appointment(uuid).is_none()); } #[test] @@ -1053,7 +1044,7 @@ mod tests { &HashSet::from_iter(vec![uuid]), &HashMap::from_iter([(appointment.user_id, info.clone())]), ); - assert!(matches!(dbm.load_appointment(uuid), Err(Error::NotFound))); + assert!(dbm.load_appointment(uuid).is_none()); // Appointment + Tracker assert!(matches!( @@ -1066,8 +1057,8 @@ mod tests { &HashSet::from_iter(vec![uuid]), &HashMap::from_iter([(appointment.user_id, info)]), ); - assert!(matches!(dbm.load_appointment(uuid), Err(Error::NotFound))); - assert!(matches!(dbm.load_tracker(uuid), Err(Error::NotFound))); + assert!(dbm.load_appointment(uuid).is_none()); + assert!(dbm.load_tracker(uuid).is_none()); } #[test] @@ -1103,7 +1094,7 @@ mod tests { let dbm = DBM::in_memory().unwrap(); let (uuid, _) = generate_dummy_appointment_with_user(get_random_user_id(), None); - assert!(matches!(dbm.load_locator(uuid), Err(Error::NotFound))); + assert!(dbm.load_locator(uuid).is_none()); } #[test] @@ -1168,7 +1159,7 @@ mod tests { let dbm = DBM::in_memory().unwrap(); let uuid = generate_uuid(); - assert!(matches!(dbm.load_tracker(uuid), Err(Error::NotFound))); + assert!(dbm.load_tracker(uuid).is_none()); } #[test] @@ -1251,14 +1242,14 @@ mod tests { fn test_store_load_nonexistent_last_known_block() { let dbm = DBM::in_memory().unwrap(); - assert!(matches!(dbm.load_last_known_block(), Err(Error::NotFound))); + assert!(dbm.load_last_known_block().is_none()); } #[test] fn test_store_load_tower_key() { let dbm = DBM::in_memory().unwrap(); - assert!(matches!(dbm.load_tower_key(), Err(Error::NotFound))); + assert!(dbm.load_tower_key().is_none()); for _ in 0..7 { let sk = get_random_keypair().0; dbm.store_tower_key(&sk).unwrap(); diff --git a/teos/src/gatekeeper.rs b/teos/src/gatekeeper.rs index 7ae8a23..d306453 100644 --- a/teos/src/gatekeeper.rs +++ b/teos/src/gatekeeper.rs @@ -356,7 +356,6 @@ mod tests { }; use lightning::chain::Listen; use teos_common::cryptography::{get_random_bytes, get_random_keypair}; - use teos_common::dbm::Error as DBError; use teos_common::test_utils::get_random_user_id; const SLOTS: u32 = 21; @@ -849,10 +848,7 @@ mod tests { .lock() .unwrap() .contains_key(user_id)); - assert!(matches!( - gatekeeper.dbm.lock().unwrap().load_user(*user_id), - Err(DBError::NotFound) - )); + assert!(gatekeeper.dbm.lock().unwrap().load_user(*user_id).is_none()); } // Check that the last_known_block_header has been properly updated diff --git a/teos/src/main.rs b/teos/src/main.rs index 97a882c..b7566b0 100644 --- a/teos/src/main.rs +++ b/teos/src/main.rs @@ -126,14 +126,11 @@ async fn main() { if conf.overwrite_key { log::info!("Overwriting tower keys"); create_new_tower_keypair(&locked_db) + } else if let Some(sk) = locked_db.load_tower_key() { + (sk, PublicKey::from_secret_key(&Secp256k1::new(), &sk)) } else { - match locked_db.load_tower_key() { - Ok(sk) => (sk, PublicKey::from_secret_key(&Secp256k1::new(), &sk)), - Err(_) => { - log::info!("Tower keys not found. Creating a fresh set"); - create_new_tower_keypair(&locked_db) - } - } + log::info!("Tower keys not found. Creating a fresh set"); + create_new_tower_keypair(&locked_db) } }; log::info!("tower_id: {tower_pk}"); @@ -179,7 +176,7 @@ async fn main() { let mut derefed = bitcoin_cli.deref(); // Load last known block from DB if found. Poll it from Bitcoind otherwise. let last_known_block = dbm.lock().unwrap().load_last_known_block(); - let tip = if let Ok(block_hash) = last_known_block { + let tip = if let Some(block_hash) = last_known_block { derefed .get_header(&block_hash, None) .await diff --git a/teos/src/responder.rs b/teos/src/responder.rs index 0a0a1cd..38efcfc 100644 --- a/teos/src/responder.rs +++ b/teos/src/responder.rs @@ -297,7 +297,7 @@ impl Responder { /// The [TransactionTracker] is queried to the [DBM]. pub(crate) fn get_tracker(&self, uuid: UUID) -> Option { if self.trackers.lock().unwrap().contains_key(&uuid) { - self.dbm.lock().unwrap().load_tracker(uuid).ok() + self.dbm.lock().unwrap().load_tracker(uuid) } else { None } @@ -623,7 +623,6 @@ mod tests { }; use teos_common::constants::IRREVOCABLY_RESOLVED; - use teos_common::dbm::Error as DBError; use teos_common::test_utils::get_random_user_id; impl PartialEq for Responder { @@ -1581,10 +1580,7 @@ mod tests { assert!(!responder.tx_tracker_map.lock().unwrap().contains_key(&txid)); // But it can be found in the database - assert!(matches!( - responder.dbm.lock().unwrap().load_tracker(uuid), - Ok(TransactionTracker { .. }) - )); + assert!(responder.dbm.lock().unwrap().load_tracker(uuid).is_some()); } } @@ -1669,10 +1665,7 @@ mod tests { for uuid in all_trackers { if target_trackers.contains(&uuid) { assert!(!responder.trackers.lock().unwrap().contains_key(&uuid)); - assert!(matches!( - responder.dbm.lock().unwrap().load_tracker(uuid), - Err(DBError::NotFound) - )); + assert!(responder.dbm.lock().unwrap().load_tracker(uuid).is_none()); let penalty_txid = &uuid_txid_map[&uuid]; // If the penalty had more than one associated uuid, only one has been deleted // (because that's how the test has been designed) @@ -1702,10 +1695,7 @@ mod tests { .lock() .unwrap() .contains_key(&uuid_txid_map[&uuid])); - assert!(matches!( - responder.dbm.lock().unwrap().load_tracker(uuid), - Ok(TransactionTracker { .. }) - )); + assert!(responder.dbm.lock().unwrap().load_tracker(uuid).is_some()); } } diff --git a/teos/src/watcher.rs b/teos/src/watcher.rs index b94d6b2..ec2e7da 100644 --- a/teos/src/watcher.rs +++ b/teos/src/watcher.rs @@ -636,11 +636,10 @@ impl Watcher { Some(a) => locators.push(a.locator), None => { if self.responder.has_tracker(*uuid) { - match dbm.load_locator(*uuid) { - Ok(locator) => locators.push(locator), - Err(_) => log::error!( - "Tracker found in Responder but not in DB (uuid = {uuid})" - ), + if let Some(locator) = dbm.load_locator(*uuid) { + locators.push(locator) + } else { + log::error!("Tracker found in Responder but not in DB (uuid = {uuid})") } } else { log::error!("Appointment found in the Gatekeeper but not in the Watcher nor the Responder (uuid = {uuid})") @@ -770,7 +769,6 @@ mod tests { SUBSCRIPTION_EXPIRY, SUBSCRIPTION_START, }; use teos_common::cryptography::{get_random_bytes, get_random_keypair}; - use teos_common::dbm::Error as DBError; use bitcoin::hash_types::Txid; use bitcoin::hashes::Hash; @@ -961,10 +959,12 @@ mod tests { // Check data was added to the database for uuid in watcher.appointments.lock().unwrap().keys() { - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(*uuid), - Ok(ExtendedAppointment { .. }) - )); + assert!(watcher + .dbm + .lock() + .unwrap() + .load_appointment(*uuid) + .is_some()); } // If an appointment is already in the Responder, it should bounce @@ -1010,14 +1010,8 @@ mod tests { assert!(watcher.responder.has_tracker(uuid)); // Check data was added to the database - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Ok(ExtendedAppointment { .. }) - )); - assert!(matches!( - watcher.dbm.lock().unwrap().load_tracker(uuid), - Ok(TransactionTracker { .. }) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_some()); + assert!(watcher.dbm.lock().unwrap().load_tracker(uuid).is_some()); // If an appointment is rejected by the Responder, it is considered misbehavior and the slot count is kept // Wrong penalty @@ -1034,14 +1028,8 @@ mod tests { assert_eq!(watcher.appointments.lock().unwrap().len(), 3); // Data should not be in the database - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Err(DBError::NotFound) - )); - assert!(matches!( - watcher.dbm.lock().unwrap().load_tracker(uuid), - Err(DBError::NotFound) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_none()); + assert!(watcher.dbm.lock().unwrap().load_tracker(uuid).is_none()); // Transaction rejected // Update the Responder with a new Carrier @@ -1062,10 +1050,7 @@ mod tests { assert_eq!(watcher.appointments.lock().unwrap().len(), 3); // Data should not be in the database - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Err(DBError::NotFound) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_none()); // FAIL cases (non-registered, subscription expired and not enough slots) @@ -1078,10 +1063,7 @@ mod tests { Err(AddAppointmentFailure::AuthenticationFailure) )); // Data should not be in the database - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Err(DBError::NotFound) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_none()); // If the user has no enough slots, the appointment is rejected. We do not test all possible cases since updates are // already tested int he Gatekeeper. Testing that it is rejected if the condition is met should suffice. @@ -1103,10 +1085,7 @@ mod tests { Err(AddAppointmentFailure::NotEnoughSlots) )); // Data should not be in the database - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Err(DBError::NotFound) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_none()); // If the user subscription has expired, the appointment should be rejected. watcher @@ -1123,10 +1102,7 @@ mod tests { Err(AddAppointmentFailure::SubscriptionExpired { .. }) )); // Data should not be in the database - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Err(DBError::NotFound) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_none()); } #[tokio::test] @@ -1211,10 +1187,7 @@ mod tests { ); // In this case the appointment is kept in the Responder and, therefore, in the database assert!(watcher.responder.has_tracker(uuid)); - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Ok(ExtendedAppointment { .. }) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_some()); // A properly formatted but invalid transaction should be rejected by the Responder // Update the Responder with a new Carrier that will reject the transaction @@ -1232,10 +1205,7 @@ mod tests { ); // In this case the appointment is not kept in the Responder nor in the database assert!(!watcher.responder.has_tracker(uuid)); - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Err { .. } - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_none()); // Invalid triggered appointments should not be passed to the Responder // Use a dispute_tx that does not match the appointment to replicate a decryption error @@ -1247,10 +1217,7 @@ mod tests { ); // The appointment is not kept anywhere assert!(!watcher.responder.has_tracker(uuid)); - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Err { .. } - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_none()); } #[tokio::test] @@ -1502,10 +1469,7 @@ mod tests { .contains_key(&locator)); // But it can be found in the database - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Ok(ExtendedAppointment { .. }) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_some()); } } @@ -1586,10 +1550,7 @@ mod tests { for uuid in all_appointments { if target_appointments.contains(&uuid) { assert!(!watcher.appointments.lock().unwrap().contains_key(&uuid)); - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Err(DBError::NotFound) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_none()); let locator = &uuid_locator_map[&uuid]; // If the penalty had more than one associated uuid, only one has been deleted @@ -1620,10 +1581,7 @@ mod tests { .lock() .unwrap() .contains_key(&uuid_locator_map[&uuid])); - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Ok(ExtendedAppointment { .. }) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_some()); } } @@ -1728,10 +1686,12 @@ mod tests { .appointments .contains_key(&uuid1) ); - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid1), - Ok(ExtendedAppointment { .. }) - )); + assert!(watcher + .dbm + .lock() + .unwrap() + .load_appointment(uuid1) + .is_some()); assert!(watcher.appointments.lock().unwrap().contains_key(&uuid2)); assert!(watcher.locator_uuid_map.lock().unwrap()[&appointment.locator()].contains(&uuid2)); @@ -1740,10 +1700,12 @@ mod tests { .appointments .contains_key(&uuid2) ); - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid2), - Ok(ExtendedAppointment { .. }) - )); + assert!(watcher + .dbm + .lock() + .unwrap() + .load_appointment(uuid2) + .is_some()); // Check triggers. Add a new appointment and trigger it with valid data. let dispute_tx = get_random_tx(); @@ -1774,14 +1736,8 @@ mod tests { ); // Data should have been kept in the database - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Ok(ExtendedAppointment { .. }) - )); - assert!(matches!( - watcher.dbm.lock().unwrap().load_tracker(uuid), - Ok(TransactionTracker { .. }) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_some()); + assert!(watcher.dbm.lock().unwrap().load_tracker(uuid).is_some()); // Check triggering with a valid formatted transaction but that is rejected by the Responder. let dispute_tx = get_random_tx(); @@ -1816,14 +1772,8 @@ mod tests { .contains_key(&uuid) ); // Data should also have been deleted from the database - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Err(DBError::NotFound) - )); - assert!(matches!( - watcher.dbm.lock().unwrap().load_tracker(uuid), - Err(DBError::NotFound) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_none()); + assert!(watcher.dbm.lock().unwrap().load_tracker(uuid).is_none()); // Checks invalid triggers. Add a new appointment and trigger it with invalid data. let dispute_tx = get_random_tx(); @@ -1855,10 +1805,7 @@ mod tests { .appointments .contains_key(&uuid) ); - assert!(matches!( - watcher.dbm.lock().unwrap().load_appointment(uuid), - Err(DBError::NotFound) - )); + assert!(watcher.dbm.lock().unwrap().load_appointment(uuid).is_none()); } #[tokio::test] diff --git a/watchtower-plugin/src/dbm.rs b/watchtower-plugin/src/dbm.rs index ec03886..bf271bb 100755 --- a/watchtower-plugin/src/dbm.rs +++ b/watchtower-plugin/src/dbm.rs @@ -125,7 +125,7 @@ impl DBM { /// /// Loads the key with higher id from the database. Old keys are not overwritten just in case a recovery is needed, /// but they are not accessible from the API either. - pub fn load_client_key(&self) -> Result { + pub fn load_client_key(&self) -> Option { let mut stmt = self .connection .prepare( @@ -137,7 +137,7 @@ impl DBM { let sk: String = row.get(0).unwrap(); Ok(SecretKey::from_str(&sk).unwrap()) }) - .map_err(|_| Error::NotFound) + .ok() } /// Stores a tower record into the database alongside the corresponding registration receipt. @@ -171,7 +171,7 @@ impl DBM { /// Tower records are composed from the tower information and the appointment data. The latter is split in: /// accepted appointments (represented by appointment receipts), pending appointments and invalid appointments. /// In the case that the tower has misbehaved, then a misbehaving proof is also attached to the record. - pub fn load_tower_record(&self, tower_id: TowerId) -> Result { + pub fn load_tower_record(&self, tower_id: TowerId) -> Option { let mut stmt = self .connection .prepare("SELECT t.net_addr, t.available_slots, r.subscription_start, r.subscription_expiry @@ -197,16 +197,16 @@ impl DBM { self.load_appointments(tower_id, AppointmentStatus::Invalid), )) }) - .map_err(|_| Error::NotFound)?; + .ok()?; - if let Ok(proof) = self.load_misbehaving_proof(tower_id) { + if let Some(proof) = self.load_misbehaving_proof(tower_id) { tower.status = TowerStatus::Misbehaving; tower.set_misbehaving_proof(proof); } else if !tower.pending_appointments.is_empty() { tower.status = TowerStatus::TemporaryUnreachable; } - Ok(tower) + Some(tower) } /// Loads the latest registration receipt for a given tower. @@ -216,7 +216,7 @@ impl DBM { &self, tower_id: TowerId, user_id: UserId, - ) -> Result { + ) -> Option { let mut stmt = self .connection .prepare( @@ -228,20 +228,17 @@ impl DBM { ) .unwrap(); - let receipt = stmt - .query_row([tower_id.to_vec()], |row| { - let slots: u32 = row.get(0).unwrap(); - let start: u32 = row.get(1).unwrap(); - let expiry: u32 = row.get(2).unwrap(); - let signature: String = row.get(3).unwrap(); + stmt.query_row([tower_id.to_vec()], |row| { + let slots: u32 = row.get(0).unwrap(); + let start: u32 = row.get(1).unwrap(); + let expiry: u32 = row.get(2).unwrap(); + let signature: String = row.get(3).unwrap(); - Ok(RegistrationReceipt::with_signature( - user_id, slots, start, expiry, signature, - )) - }) - .map_err(|_| Error::NotFound)?; - - Ok(receipt) + Ok(RegistrationReceipt::with_signature( + user_id, slots, start, expiry, signature, + )) + }) + .ok() } /// Removes a tower record from the database. @@ -333,7 +330,7 @@ impl DBM { &self, tower_id: TowerId, locator: Locator, - ) -> Result { + ) -> Option { let mut stmt = self .connection .prepare("SELECT start_block, user_signature, tower_signature FROM appointment_receipts WHERE tower_id = ?1 and locator = ?2") @@ -350,7 +347,7 @@ impl DBM { tower_sig, )) }) - .map_err(|_| Error::NotFound) + .ok() } /// Loads the appointment receipts associated to a given tower. @@ -406,7 +403,7 @@ impl DBM { } /// Loads an appointment from the database. - pub fn load_appointment(&self, locator: Locator) -> Result { + pub fn load_appointment(&self, locator: Locator) -> Option { let mut stmt = self .connection .prepare("SELECT encrypted_blob, to_self_delay FROM appointments WHERE locator = ?") @@ -418,7 +415,7 @@ impl DBM { Ok(Appointment::new(locator, encrypted_blob, to_self_delay)) }) - .map_err(|_| Error::NotFound) + .ok() } /// Stores an appointment into the database. @@ -598,7 +595,7 @@ impl DBM { } /// Loads the misbehaving proof for a given tower from the database (if found). - fn load_misbehaving_proof(&self, tower_id: TowerId) -> Result { + fn load_misbehaving_proof(&self, tower_id: TowerId) -> Option { let mut misbehaving_stmt = self .connection .prepare("SELECT locator, recovered_id FROM misbehaving_proofs WHERE tower_id = ?") @@ -633,7 +630,7 @@ impl DBM { .unwrap(); MisbehaviorProof::new(locator, receipt, recovered_id) }) - .map_err(|_| Error::NotFound) + .ok() } /// Checks whether a misbehaving proof exists for a given tower. @@ -792,10 +789,7 @@ mod tests { // If the tower does not exists, `load_tower` will fail. let tower_id = get_random_user_id(); - assert!(matches!( - dbm.load_tower_record(tower_id), - Err(Error::NotFound) - )); + assert!(dbm.load_tower_record(tower_id).is_none()); } #[test] @@ -917,10 +911,9 @@ mod tests { // If there is no appointment receipt for the given (locator, tower_id) pair, Error::NotFound is returned // Try first with both being unknown - assert!(matches!( - dbm.load_appointment_receipt(tower_id, appointment.locator), - Err(Error::NotFound) - )); + assert!(dbm + .load_appointment_receipt(tower_id, appointment.locator) + .is_none()); // Add the tower but not the appointment and try again let net_addr = "talaia.watch"; @@ -928,10 +921,9 @@ mod tests { dbm.store_tower_record(tower_id, net_addr, &receipt) .unwrap(); - assert!(matches!( - dbm.load_appointment_receipt(tower_id, appointment.locator), - Err(Error::NotFound) - )); + assert!(dbm + .load_appointment_receipt(tower_id, appointment.locator) + .is_none()); // Add both let tower_summary = TowerSummary::new( @@ -1045,7 +1037,7 @@ mod tests { let locator = generate_random_appointment(None).locator; let loaded_appointment = dbm.load_appointment(locator); - assert!(matches!(loaded_appointment, Err(Error::NotFound))); + assert!(loaded_appointment.is_none()); } #[test] @@ -1284,10 +1276,7 @@ mod tests { #[test] fn test_store_load_non_existing_misbehaving_proof() { let dbm = DBM::in_memory().unwrap(); - assert!(matches!( - dbm.load_misbehaving_proof(get_random_user_id()), - Err(Error::NotFound) - )); + assert!(dbm.load_misbehaving_proof(get_random_user_id()).is_none()); } #[test] @@ -1340,7 +1329,7 @@ mod tests { fn test_store_load_client_key() { let dbm = DBM::in_memory().unwrap(); - assert!(matches!(dbm.load_client_key(), Err(Error::NotFound))); + assert!(dbm.load_client_key().is_none()); for _ in 0..7 { let sk = get_random_keypair().0; dbm.store_client_key(&sk).unwrap(); diff --git a/watchtower-plugin/src/main.rs b/watchtower-plugin/src/main.rs index f7c0fbf..3d4910c 100755 --- a/watchtower-plugin/src/main.rs +++ b/watchtower-plugin/src/main.rs @@ -136,11 +136,13 @@ async fn get_registration_receipt( let tower_id = TowerId::try_from(v).map_err(|x| anyhow!(x))?; let state = plugin.state().lock().unwrap(); - let response = state.get_registration_receipt(tower_id).map_err(|_| { - anyhow!("Cannot find {tower_id} within the known towers. Have you registered?") - })?; - - Ok(json!(response)) + if let Some(response) = state.get_registration_receipt(tower_id) { + Ok(json!(response)) + } else { + Err(anyhow!( + "Cannot find {tower_id} within the known towers. Have you registered?" + )) + } } /// Gets the subscription information directly form the tower. @@ -244,24 +246,20 @@ async fn get_appointment_receipt( let params = GetAppointmentParams::try_from(v).map_err(|x| anyhow!(x))?; let state = plugin.state().lock().unwrap(); - let response = state - .get_appointment_receipt(params.tower_id, params.locator) - .map_err(|_| { - if state.towers.contains_key(¶ms.tower_id) { - anyhow!( - "Cannot find {} within {}. Did you send that appointment?", - params.locator, - params.tower_id - ) - } else { - anyhow!( - "Cannot find {} within the known towers. Have you registered?", - params.tower_id - ) - } - })?; - - Ok(json!(response)) + if let Some(r) = state.get_appointment_receipt(params.tower_id, params.locator) { + Ok(json!(r)) + } else if state.towers.contains_key(¶ms.tower_id) { + Err(anyhow!( + "Cannot find {} within {}. Did you send that appointment?", + params.locator, + params.tower_id + )) + } else { + Err(anyhow!( + "Cannot find {} within the known towers. Have you registered?", + params.tower_id + )) + } } /// Lists all the registered towers. @@ -283,15 +281,18 @@ async fn get_tower_info( ) -> Result { let state = plugin.state().lock().unwrap(); let tower_id = TowerId::try_from(v).map_err(|e| anyhow!(e))?; - let tower_info = state.load_tower_info(tower_id).map_err(|_| { - anyhow!("Cannot find {tower_id} within the known towers. Have you registered?") - })?; - // Notice we need to check the status in memory since we cannot distinguish between unreachable and temporary unreachable - // by just checking the data in the database. - Ok(json!( - tower_info.with_status(state.get_tower_status(&tower_id).unwrap()) - )) + if let Some(tower_info) = state.load_tower_info(tower_id) { + // Notice we need to check the status in memory since we cannot distinguish between unreachable and temporary unreachable + // by just checking the data in the database. + Ok(json!( + tower_info.with_status(state.get_tower_status(&tower_id).unwrap()) + )) + } else { + Err(anyhow!( + "Cannot find {tower_id} within the known towers. Have you registered?", + )) + } } /// Triggers a manual retry of a tower, tries to send all pending appointments to it. diff --git a/watchtower-plugin/src/wt_client.rs b/watchtower-plugin/src/wt_client.rs index 315d9aa..ecf26db 100644 --- a/watchtower-plugin/src/wt_client.rs +++ b/watchtower-plugin/src/wt_client.rs @@ -95,17 +95,17 @@ impl WTClient { }); let dbm = DBM::new(&data_dir.join("watchtowers_db.sql3")).unwrap(); - let (user_sk, user_id) = match dbm.load_client_key() { - Ok(sk) => ( + + let (user_sk, user_id) = if let Some(sk) = dbm.load_client_key() { + ( sk, UserId(PublicKey::from_secret_key(&Secp256k1::new(), &sk)), - ), - Err(_) => { - log::info!("Watchtower client keys not found. Creating a fresh set"); - let (sk, pk) = cryptography::get_random_keypair(); - dbm.store_client_key(&sk).unwrap(); - (sk, UserId(pk)) - } + ) + } else { + log::info!("Watchtower client keys not found. Creating a fresh set"); + let (sk, pk) = cryptography::get_random_keypair(); + dbm.store_client_key(&sk).unwrap(); + (sk, UserId(pk)) }; let towers = dbm.load_towers(); @@ -180,15 +180,12 @@ impl WTClient { } /// Gets the latest registration receipt of a given tower. - pub fn get_registration_receipt( - &self, - tower_id: TowerId, - ) -> Result { + pub fn get_registration_receipt(&self, tower_id: TowerId) -> Option { self.dbm.load_registration_receipt(tower_id, self.user_id) } /// Loads a tower record from the database. - pub fn load_tower_info(&self, tower_id: TowerId) -> Result { + pub fn load_tower_info(&self, tower_id: TowerId) -> Option { self.dbm.load_tower_record(tower_id) } @@ -240,7 +237,7 @@ impl WTClient { &self, tower_id: TowerId, locator: Locator, - ) -> Result { + ) -> Option { self.dbm.load_appointment_receipt(tower_id, locator) } @@ -810,10 +807,7 @@ mod tests { // Remove the tower and check it is not there anymore wt_client.remove_tower(tower_id).unwrap(); - assert!(matches!( - wt_client.load_tower_info(tower_id), - Err(DBError::NotFound) - )); + assert!(wt_client.load_tower_info(tower_id).is_none()); assert!(!wt_client.towers.contains_key(&tower_id)); // Try again but this time with an associated appointment to check that it also gets removed @@ -836,10 +830,7 @@ mod tests { // Remove and check both the tower and the appointment wt_client.remove_tower(tower_id).unwrap(); - assert!(matches!( - wt_client.load_tower_info(tower_id), - Err(DBError::NotFound) - )); + assert!(wt_client.load_tower_info(tower_id).is_none()); assert!(!wt_client.towers.contains_key(&tower_id)); assert!(!wt_client.dbm.appointment_receipt_exists(locator, tower_id)); } @@ -890,10 +881,7 @@ mod tests { // Remove tower1 and check that the appointment receipt can still be found for tower2 wt_client.remove_tower(tower1_id).unwrap(); - assert!(matches!( - wt_client.load_tower_info(tower1_id), - Err(DBError::NotFound) - )); + assert!(wt_client.load_tower_info(tower1_id).is_none()); assert!(!wt_client.dbm.appointment_receipt_exists(locator, tower1_id)); assert!(wt_client.dbm.appointment_receipt_exists(locator, tower2_id));