Improves overall memory management

Refactors severals parts of the code so:

- Copy values are not passed as reference
- Copy values are derefered when needed instead of cloned
- Clones are avoided as much as possible
- Strings are replaced by &str when possible

More passes to the code may be necessary in the future, but this is a good start
This commit is contained in:
Sergi Delgado Segura 2021-12-03 15:39:23 +01:00
parent fc5ac0e8dc
commit 8a8772df99
9 changed files with 315 additions and 340 deletions

View file

@ -20,8 +20,8 @@ impl RegistrationReceipt {
}
}
pub fn user_id(&self) -> &UserId {
&self.user_id
pub fn user_id(&self) -> UserId {
self.user_id
}
pub fn available_slots(&self) -> u32 {
@ -66,8 +66,8 @@ impl AppointmentReceipt {
}
}
pub fn user_signature(&self) -> String {
self.user_signature.clone()
pub fn user_signature(&self) -> &str {
&self.user_signature
}
pub fn start_block(&self) -> u32 {

View file

@ -20,15 +20,15 @@ use lightning_block_sync::http::HttpEndpoint;
use lightning_block_sync::rpc::RpcClient;
use lightning_block_sync::{AsyncBlockSourceResult, BlockHeaderData, BlockSource};
pub struct BitcoindClient {
pub struct BitcoindClient<'a> {
bitcoind_rpc_client: Arc<Mutex<RpcClient>>,
host: String,
host: &'a str,
port: u16,
rpc_user: String,
rpc_password: String,
rpc_user: &'a str,
rpc_password: &'a str,
}
impl BlockSource for &BitcoindClient {
impl BlockSource for &BitcoindClient<'_> {
fn get_header<'a>(
&'a mut self,
header_hash: &'a BlockHash,
@ -58,16 +58,15 @@ impl BlockSource for &BitcoindClient {
}
}
impl BitcoindClient {
impl<'a> BitcoindClient<'a> {
pub async fn new(
host: String,
host: &'a str,
port: u16,
rpc_user: String,
rpc_password: String,
) -> std::io::Result<Self> {
let http_endpoint = HttpEndpoint::for_host(host.clone()).with_port(port);
let rpc_credentials =
base64::encode(format!("{}:{}", rpc_user.clone(), rpc_password.clone()));
rpc_user: &'a str,
rpc_password: &'a str,
) -> std::io::Result<BitcoindClient<'a>> {
let http_endpoint = HttpEndpoint::for_host(host.to_owned()).with_port(port);
let rpc_credentials = base64::encode(format!("{}:{}", rpc_user, rpc_password));
let bitcoind_rpc_client = RpcClient::new(&rpc_credentials, http_endpoint)?;
let client = Self {
@ -86,12 +85,8 @@ impl BitcoindClient {
}
pub fn get_new_rpc_client(&self) -> std::io::Result<RpcClient> {
let http_endpoint = HttpEndpoint::for_host(self.host.clone()).with_port(self.port);
let rpc_credentials = base64::encode(format!(
"{}:{}",
self.rpc_user.clone(),
self.rpc_password.clone()
));
let http_endpoint = HttpEndpoint::for_host(self.host.to_owned()).with_port(self.port);
let rpc_credentials = base64::encode(format!("{}:{}", self.rpc_user, self.rpc_password));
RpcClient::new(&rpc_credentials, http_endpoint)
}

View file

@ -133,7 +133,7 @@ impl DBM {
self.remove_data(query, params)
}
pub fn store_user(&self, user_id: &UserId, user_info: &UserInfo) -> Result<(), Error> {
pub fn store_user(&self, user_id: UserId, user_info: &UserInfo) -> Result<(), Error> {
let query =
"INSERT INTO users (user_id, available_slots, subscription_expiry) VALUES (?1, ?2, ?3)";
@ -156,7 +156,7 @@ impl DBM {
}
}
pub fn update_user(&self, user_id: &UserId, user_info: &UserInfo) {
pub fn update_user(&self, user_id: UserId, user_info: &UserInfo) {
let query =
"UPDATE users SET available_slots=(?1), subscription_expiry=(?2) WHERE user_id=(?3)";
match self.update_data(
@ -178,7 +178,7 @@ impl DBM {
// DISCUSS: This could be implemented with an INNER JOIN query, but the logic will be more complex given each row
// will have the user info replicated. Consider whether it makes sense to change it.
pub fn load_user(&self, user_id: &UserId) -> Result<UserInfo, Error> {
pub fn load_user(&self, user_id: UserId) -> Result<UserInfo, Error> {
let key = user_id.serialize();
let mut stmt = self
.connection
@ -235,7 +235,7 @@ impl DBM {
users
}
pub fn remove_user(&self, user_id: &UserId) {
pub fn remove_user(&self, user_id: UserId) {
let query = "DELETE FROM users WHERE user_id=(?)";
match self.remove_data(query, params![user_id.serialize()]) {
Ok(_) => {
@ -249,7 +249,7 @@ impl DBM {
pub fn store_appointment(
&self,
uuid: &UUID,
uuid: UUID,
appointment: &ExtendedAppointment,
) -> Result<(), Error> {
let query = "INSERT INTO appointments (UUID, locator, encrypted_blob, to_self_delay, user_signature, start_block, user_id) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)";
@ -276,7 +276,7 @@ impl DBM {
}
}
pub fn update_appointment(&self, uuid: &UUID, appointment: &ExtendedAppointment) {
pub fn update_appointment(&self, uuid: UUID, appointment: &ExtendedAppointment) {
// DISCUSS: Check what fields we'd like to make updatable. e_blob and signature are the obvious, to_self_delay and start_block may not be necessary (or even risky)
let query =
"UPDATE appointments SET encrypted_blob=(?1), to_self_delay=(?2), user_signature=(?3), start_block=(?4) WHERE UUID=(?5)";
@ -299,7 +299,7 @@ impl DBM {
}
}
pub fn load_appointment(&self, uuid: &UUID) -> Result<ExtendedAppointment, Error> {
pub fn load_appointment(&self, uuid: UUID) -> Result<ExtendedAppointment, Error> {
let key = uuid.serialize();
let mut stmt = self
.connection
@ -355,7 +355,7 @@ impl DBM {
appointments
}
pub fn remove_appointment(&self, uuid: &UUID) {
pub fn remove_appointment(&self, uuid: UUID) {
let query = "DELETE FROM appointments WHERE UUID=(?)";
match self.remove_data(query, params![uuid.serialize()]) {
Ok(_) => {
@ -389,7 +389,7 @@ impl DBM {
(appointments.len() as f64 / limit as f64).ceil() as usize
}
pub fn store_tracker(&self, uuid: &UUID, tracker: &TransactionTracker) -> Result<(), Error> {
pub fn store_tracker(&self, uuid: UUID, tracker: &TransactionTracker) -> Result<(), Error> {
let query = "INSERT INTO trackers (UUID, dispute_tx, penalty_tx) VALUES (?1, ?2, ?3)";
match self.store_data(
query,
@ -410,7 +410,7 @@ impl DBM {
}
}
pub fn load_tracker(&self, uuid: &UUID) -> Result<TransactionTracker, Error> {
pub fn load_tracker(&self, uuid: UUID) -> Result<TransactionTracker, Error> {
let key = uuid.serialize();
let mut stmt = self.connection.prepare(
"SELECT t.*, a.locator, a.user_id FROM trackers as t INNER JOIN appointments as a ON t.UUID=a.UUID WHERE t.UUID=(?)").unwrap();
@ -587,13 +587,13 @@ mod tests {
let user_id = get_random_user_id();
let mut user = UserInfo::new(21, 42);
assert!(matches!(dbm.store_user(&user_id, &user), Ok { .. }));
assert_eq!(dbm.load_user(&user_id).unwrap(), user);
assert!(matches!(dbm.store_user(user_id, &user), Ok { .. }));
assert_eq!(dbm.load_user(user_id).unwrap(), user);
// User info should be updatable but only via the update_user method
user = UserInfo::new(42, 21);
assert!(matches!(
dbm.store_user(&user_id, &user),
dbm.store_user(user_id, &user),
Err(Error::AlreadyExists)
));
}
@ -605,16 +605,16 @@ mod tests {
let user_id = get_random_user_id();
let mut user = UserInfo::new(21, 42);
dbm.store_user(&user_id, &user).unwrap();
dbm.store_user(user_id, &user).unwrap();
// Add some appointments to the user
for _ in 0..10 {
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
dbm.store_appointment(&uuid, &appointment).unwrap();
dbm.store_appointment(uuid, &appointment).unwrap();
user.appointments.insert(uuid, 1);
}
assert_eq!(dbm.load_user(&user_id).unwrap(), user);
assert_eq!(dbm.load_user(user_id).unwrap(), user);
}
#[test]
@ -622,7 +622,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!(matches!(dbm.load_user(user_id), Err(Error::NotFound)));
}
#[test]
@ -632,12 +632,12 @@ mod tests {
let user_id = get_random_user_id();
let mut user = UserInfo::new(21, 42);
dbm.store_user(&user_id, &user).unwrap();
assert_eq!(dbm.load_user(&user_id).unwrap(), user);
dbm.store_user(user_id, &user).unwrap();
assert_eq!(dbm.load_user(user_id).unwrap(), user);
user.available_slots *= 2;
dbm.update_user(&user_id, &user);
assert_eq!(dbm.load_user(&user_id).unwrap(), user);
dbm.update_user(user_id, &user);
assert_eq!(dbm.load_user(user_id).unwrap(), user);
}
#[test]
@ -649,7 +649,7 @@ mod tests {
let user_id = get_random_user_id();
let user = UserInfo::new(i, i * 2);
users.insert(user_id, user.clone());
dbm.store_user(&user_id, &user).unwrap();
dbm.store_user(user_id, &user).unwrap();
}
assert_eq!(dbm.load_all_users(), users);
@ -661,10 +661,10 @@ mod tests {
let user_id = get_random_user_id();
let user = UserInfo::new(21, 42);
assert!(matches!(dbm.store_user(&user_id, &user), Ok { .. }));
assert!(matches!(dbm.store_user(user_id, &user), Ok { .. }));
dbm.remove_user(&user_id);
assert!(matches!(dbm.load_user(&user_id), Err(Error::NotFound)));
dbm.remove_user(user_id);
assert!(matches!(dbm.load_user(user_id), Err(Error::NotFound)));
}
#[test]
@ -673,7 +673,7 @@ mod tests {
let user_id = get_random_user_id();
// Test it does not fail even if the user does not exist (it will log though)
dbm.remove_user(&user_id);
dbm.remove_user(user_id);
}
#[test]
@ -683,19 +683,19 @@ mod tests {
// In order to add an appointment we need the associated user to be present
let user_id = get_random_user_id();
let user = UserInfo::new(21, 42);
dbm.store_user(&user_id, &user).unwrap();
dbm.store_user(user_id, &user).unwrap();
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
assert!(matches!(
dbm.store_appointment(&uuid, &appointment),
dbm.store_appointment(uuid, &appointment),
Ok { .. }
));
assert_eq!(dbm.load_appointment(&uuid).unwrap(), appointment);
assert_eq!(dbm.load_appointment(uuid).unwrap(), appointment);
// Appointment info should be updatable but only via the update_appointment method
assert!(matches!(
dbm.store_appointment(&uuid, &appointment),
dbm.store_appointment(uuid, &appointment),
Err(Error::AlreadyExists)
));
}
@ -708,10 +708,10 @@ mod tests {
let appointment = generate_dummy_appointment(None);
assert!(matches!(
dbm.store_appointment(&uuid, &appointment),
dbm.store_appointment(uuid, &appointment),
Err(Error::MissingForeignKey)
));
assert!(matches!(dbm.load_tracker(&uuid), Err(Error::NotFound)));
assert!(matches!(dbm.load_tracker(uuid), Err(Error::NotFound)));
}
#[test]
@ -719,7 +719,7 @@ mod tests {
let dbm = DBM::in_memory().unwrap();
let uuid = generate_uuid();
assert!(matches!(dbm.load_appointment(&uuid), Err(Error::NotFound)));
assert!(matches!(dbm.load_appointment(uuid), Err(Error::NotFound)));
}
#[test]
@ -728,11 +728,11 @@ mod tests {
let user_id = get_random_user_id();
let user = UserInfo::new(21, 42);
dbm.store_user(&user_id, &user).unwrap();
dbm.store_user(user_id, &user).unwrap();
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
assert!(matches!(
dbm.store_appointment(&uuid, &appointment),
dbm.store_appointment(uuid, &appointment),
Ok { .. }
));
@ -745,10 +745,10 @@ mod tests {
another_modified_appointment.user_id = get_random_user_id();
// Check how only the modifiable fields have been updated
dbm.update_appointment(&uuid, &another_modified_appointment);
assert_eq!(dbm.load_appointment(&uuid).unwrap(), modified_appointment);
dbm.update_appointment(uuid, &another_modified_appointment);
assert_eq!(dbm.load_appointment(uuid).unwrap(), modified_appointment);
assert_ne!(
dbm.load_appointment(&uuid).unwrap(),
dbm.load_appointment(uuid).unwrap(),
another_modified_appointment
);
}
@ -761,10 +761,10 @@ mod tests {
for i in 1..11 {
let user_id = get_random_user_id();
let user = UserInfo::new(i, i * 2);
dbm.store_user(&user_id, &user).unwrap();
dbm.store_user(user_id, &user).unwrap();
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
dbm.store_appointment(&uuid, &appointment).unwrap();
dbm.store_appointment(uuid, &appointment).unwrap();
appointments.insert(uuid, appointment);
}
@ -774,14 +774,14 @@ mod tests {
// as a triggered appointment
let user_id = get_random_user_id();
let user = UserInfo::new(21, 42);
dbm.store_user(&user_id, &user).unwrap();
dbm.store_user(user_id, &user).unwrap();
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
dbm.store_appointment(&uuid, &appointment).unwrap();
dbm.store_appointment(uuid, &appointment).unwrap();
let mut tracker = get_random_tracker(user_id);
tracker.locator = appointment.locator();
dbm.store_tracker(&uuid, &tracker).unwrap();
dbm.store_tracker(uuid, &tracker).unwrap();
// We should get all the appointments back except from the triggered one
assert_eq!(dbm.load_all_appointments(), appointments);
@ -792,15 +792,15 @@ mod tests {
let dbm = DBM::in_memory().unwrap();
let user_id = get_random_user_id();
let user = UserInfo::new(21, 42);
dbm.store_user(&user_id, &user).unwrap();
dbm.store_user(user_id, &user).unwrap();
// Store and delete appointment
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
dbm.store_appointment(&uuid, &appointment).unwrap();
assert_eq!(dbm.load_appointment(&uuid).unwrap(), appointment);
dbm.remove_appointment(&uuid);
dbm.store_appointment(uuid, &appointment).unwrap();
assert_eq!(dbm.load_appointment(uuid).unwrap(), appointment);
dbm.remove_appointment(uuid);
assert!(matches!(dbm.load_appointment(&uuid), Err(Error::NotFound)));
assert!(matches!(dbm.load_appointment(uuid), Err(Error::NotFound)));
}
#[test]
@ -808,10 +808,10 @@ mod tests {
let dbm = DBM::in_memory().unwrap();
let user_id = get_random_user_id();
let user = UserInfo::new(21, 42);
dbm.store_user(&user_id, &user).unwrap();
dbm.store_user(user_id, &user).unwrap();
// Test it does not fail even if the appointment does not exist (it will log though)
dbm.remove_appointment(&generate_uuid());
dbm.remove_appointment(generate_uuid());
}
#[test]
@ -822,17 +822,17 @@ mod tests {
// at the same time requires an associated user to be present)
let user_id = get_random_user_id();
let user = UserInfo::new(21, 42);
dbm.store_user(&user_id, &user).unwrap();
dbm.store_user(user_id, &user).unwrap();
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
dbm.store_appointment(&uuid, &appointment).unwrap();
dbm.store_appointment(uuid, &appointment).unwrap();
let mut tracker = get_random_tracker(user_id);
// Set the locator to match between appointment and tracker
tracker.locator = appointment.locator();
assert!(matches!(dbm.store_tracker(&uuid, &tracker), Ok { .. }));
assert_eq!(dbm.load_tracker(&uuid).unwrap(), tracker);
assert!(matches!(dbm.store_tracker(uuid, &tracker), Ok { .. }));
assert_eq!(dbm.load_tracker(uuid).unwrap(), tracker);
}
#[test]
@ -841,18 +841,18 @@ mod tests {
let user_id = get_random_user_id();
let user = UserInfo::new(21, 42);
dbm.store_user(&user_id, &user).unwrap();
dbm.store_user(user_id, &user).unwrap();
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
dbm.store_appointment(&uuid, &appointment).unwrap();
dbm.store_appointment(uuid, &appointment).unwrap();
let mut tracker = get_random_tracker(user_id);
tracker.locator = appointment.locator();
assert!(matches!(dbm.store_tracker(&uuid, &tracker), Ok { .. }));
assert!(matches!(dbm.store_tracker(uuid, &tracker), Ok { .. }));
// Try to store it again, but it shouldn't go trough
assert!(matches!(
dbm.store_tracker(&uuid, &tracker),
dbm.store_tracker(uuid, &tracker),
Err(Error::AlreadyExists)
));
}
@ -866,7 +866,7 @@ mod tests {
let tracker = get_random_tracker(user_id);
assert!(matches!(
dbm.store_tracker(&uuid, &tracker),
dbm.store_tracker(uuid, &tracker),
Err(Error::MissingForeignKey)
));
}
@ -876,7 +876,7 @@ mod tests {
let dbm = DBM::in_memory().unwrap();
let uuid = generate_uuid();
assert!(matches!(dbm.load_tracker(&uuid), Err(Error::NotFound)));
assert!(matches!(dbm.load_tracker(uuid), Err(Error::NotFound)));
}
#[test]
@ -887,14 +887,14 @@ mod tests {
for i in 1..11 {
let user_id = get_random_user_id();
let user = UserInfo::new(i, i * 2);
dbm.store_user(&user_id, &user).unwrap();
dbm.store_user(user_id, &user).unwrap();
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
dbm.store_appointment(&uuid, &appointment).unwrap();
dbm.store_appointment(uuid, &appointment).unwrap();
let mut tracker = get_random_tracker(user_id);
tracker.locator = appointment.locator();
dbm.store_tracker(&uuid, &tracker).unwrap();
dbm.store_tracker(uuid, &tracker).unwrap();
trackers.insert(uuid, tracker);
}
@ -986,14 +986,14 @@ mod tests {
let user_id = get_random_user_id();
let user = UserInfo::new(21, 42);
dbm.store_user(&user_id, &user).unwrap();
dbm.store_user(user_id, &user).unwrap();
let mut rest = HashSet::new();
for i in 1..6 {
let mut to_be_deleted = HashSet::new();
for j in 0..limit * 2 * i {
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
dbm.store_appointment(&uuid, &appointment).unwrap();
dbm.store_appointment(uuid, &appointment).unwrap();
if j % 2 == 0 {
to_be_deleted.insert(uuid);
@ -1021,31 +1021,31 @@ mod tests {
let tracker = get_random_tracker(appointment.user_id);
// Add the user b/c of FK restrictions
dbm.store_user(&appointment.user_id, &UserInfo::new(21, 42))
dbm.store_user(appointment.user_id, &UserInfo::new(21, 42))
.unwrap();
// Appointment only
assert!(matches!(
dbm.store_appointment(&uuid, &appointment.clone()),
dbm.store_appointment(uuid, &appointment.clone()),
Ok { .. }
));
dbm.batch_remove_appointments(&HashSet::from_iter(vec![uuid]));
assert!(matches!(dbm.load_appointment(&uuid), Err(Error::NotFound)));
assert!(matches!(dbm.load_appointment(uuid), Err(Error::NotFound)));
// Appointment + Tracker
assert!(matches!(
dbm.store_appointment(&uuid, &appointment.clone()),
dbm.store_appointment(uuid, &appointment.clone()),
Ok { .. }
));
assert!(matches!(
dbm.store_tracker(&uuid, &tracker.clone()),
dbm.store_tracker(uuid, &tracker.clone()),
Ok { .. }
));
dbm.batch_remove_appointments(&HashSet::from_iter(vec![uuid]));
assert!(matches!(dbm.load_appointment(&uuid), Err(Error::NotFound)));
assert!(matches!(dbm.load_tracker(&uuid), Err(Error::NotFound)));
assert!(matches!(dbm.load_appointment(uuid), Err(Error::NotFound)));
assert!(matches!(dbm.load_tracker(uuid), Err(Error::NotFound)));
}
#[test]
@ -1073,19 +1073,19 @@ mod tests {
user_id,
);
dbm.store_user(&user_id, &user).unwrap();
dbm.store_appointment(&uuid, &appointment).unwrap();
dbm.store_tracker(&uuid, &tracker).unwrap();
dbm.store_user(user_id, &user).unwrap();
dbm.store_appointment(uuid, &appointment).unwrap();
dbm.store_tracker(uuid, &tracker).unwrap();
// Check data is in the DB (this is implicitly checked by the unwraps, but anyway)
assert_eq!(dbm.load_user(&user_id).unwrap(), user);
assert_eq!(dbm.load_appointment(&uuid).unwrap(), appointment);
assert_eq!(dbm.load_tracker(&uuid).unwrap(), tracker);
assert_eq!(dbm.load_user(user_id).unwrap(), user);
assert_eq!(dbm.load_appointment(uuid).unwrap(), appointment);
assert_eq!(dbm.load_tracker(uuid).unwrap(), tracker);
// Remove the user and check again
dbm.remove_user(&user_id);
assert!(matches!(dbm.load_user(&user_id), Err(Error::NotFound)));
assert!(matches!(dbm.load_appointment(&uuid), Err(Error::NotFound)));
assert!(matches!(dbm.load_tracker(&uuid), Err(Error::NotFound)));
dbm.remove_user(user_id);
assert!(matches!(dbm.load_user(user_id), Err(Error::NotFound)));
assert!(matches!(dbm.load_appointment(uuid), Err(Error::NotFound)));
assert!(matches!(dbm.load_tracker(uuid), Err(Error::NotFound)));
}
}

View file

@ -9,7 +9,7 @@ use teos_common::UserId;
pub struct UUID(pub [u8; 20]);
impl UUID {
pub fn new(locator: &Locator, user_id: &UserId) -> Self {
pub fn new(locator: Locator, user_id: UserId) -> Self {
let mut uuid_data = locator.serialize();
uuid_data.extend(&user_id.0.serialize());
UUID(ripemd160::Hash::hash(&uuid_data).into_inner())

View file

@ -88,15 +88,12 @@ impl Gatekeeper {
}
}
pub fn add_update_user(
&self,
user_id: &UserId,
) -> Result<RegistrationReceipt, MaxSlotsReached> {
pub fn add_update_user(&self, user_id: UserId) -> Result<RegistrationReceipt, MaxSlotsReached> {
let block_count = self.last_known_block_header.height;
// TODO: For now, new calls to register add subscription_slots to the current count and reset the expiry time
let mut borrowed = self.registered_users.borrow_mut();
let user_info = match borrowed.get_mut(user_id) {
let user_info = match borrowed.get_mut(&user_id) {
// User already exists, updating the info
Some(user_info) => {
user_info.available_slots = user_info
@ -106,7 +103,7 @@ impl Gatekeeper {
user_info.subscription_expiry = block_count + self.subscription_duration;
self.dbm.lock().unwrap().update_user(user_id, &user_info);
user_info.clone()
user_info
}
// New user
None => {
@ -114,19 +111,19 @@ impl Gatekeeper {
self.subscription_slots,
block_count + self.subscription_duration,
);
borrowed.insert(user_id.clone(), user_info.clone());
self.dbm
.lock()
.unwrap()
.store_user(user_id, &user_info)
.unwrap();
user_info
borrowed.insert(user_id, user_info);
borrowed.get_mut(&user_id).unwrap()
}
};
Ok(RegistrationReceipt::new(
user_id.clone(),
user_id,
user_info.available_slots,
user_info.subscription_expiry,
))
@ -134,14 +131,14 @@ impl Gatekeeper {
pub fn add_update_appointment(
&self,
user_id: &UserId,
user_id: UserId,
uuid: UUID,
appointment: &ExtendedAppointment,
) -> Result<u32, NotEnoughSlots> {
// For updates, the difference between the existing appointment size and the update is computed.
let mut borrowed = self.registered_users.borrow_mut();
let user_info = borrowed.get_mut(user_id).unwrap();
let used_slots = user_info.appointments.get(&uuid).map_or(0, |x| x.clone());
let user_info = borrowed.get_mut(&user_id).unwrap();
let used_slots = user_info.appointments.get(&uuid).map_or(0, |x| *x);
let required_slots =
compute_appointment_slots(appointment.encrypted_blob().len(), ENCRYPTED_BLOB_MAX_SIZE);
@ -163,7 +160,7 @@ impl Gatekeeper {
pub fn has_subscription_expired(
&self,
user_id: &UserId,
user_id: UserId,
) -> Result<(bool, u32), AuthenticationFailure<'_>> {
self.registered_users.borrow().get(&user_id).map_or(
Err(AuthenticationFailure("User not found.")),
@ -176,17 +173,15 @@ impl Gatekeeper {
)
}
pub fn get_outdated_users(&self, block_height: &u32) -> HashMap<UserId, Vec<UUID>> {
match self.outdated_users_cache.borrow().get(&block_height) {
pub fn get_outdated_users(&self, block_height: u32) -> HashMap<UserId, Vec<UUID>> {
let borrowed = self.outdated_users_cache.borrow();
match borrowed.get(&block_height) {
Some(users) => users.clone(),
None => {
let mut users = HashMap::new();
for (user_id, user_info) in self.registered_users.borrow().iter() {
if *block_height == user_info.subscription_expiry + self.expiry_delta {
users.insert(
user_id.clone(),
user_info.appointments.keys().cloned().collect(),
);
if block_height == user_info.subscription_expiry + self.expiry_delta {
users.insert(*user_id, user_info.appointments.keys().cloned().collect());
}
}
@ -194,14 +189,14 @@ impl Gatekeeper {
}
}
}
pub fn get_outdated_user_ids(&self, block_height: &u32) -> Vec<UserId> {
pub fn get_outdated_user_ids(&self, block_height: u32) -> Vec<UserId> {
self.get_outdated_users(block_height)
.keys()
.cloned()
.collect()
}
pub fn get_outdated_appointments(&self, block_height: &u32) -> HashSet<UUID> {
pub fn get_outdated_appointments(&self, block_height: u32) -> HashSet<UUID> {
HashSet::from_iter(
self.get_outdated_users(block_height)
.into_values()
@ -209,7 +204,7 @@ impl Gatekeeper {
)
}
pub fn update_outdated_users_cache(&self, block_height: &u32) -> HashMap<UserId, Vec<UUID>> {
pub fn update_outdated_users_cache(&self, block_height: u32) -> HashMap<UserId, Vec<UUID>> {
let mut outdated_users = HashMap::new();
if !self
@ -232,7 +227,7 @@ impl Gatekeeper {
// TODO: This can be implemented as a batch delete
borrowed.remove(&first).map(|users| {
for user_id in users.keys() {
self.dbm.lock().unwrap().remove_user(user_id);
self.dbm.lock().unwrap().remove_user(*user_id);
}
});
}
@ -261,7 +256,7 @@ impl Gatekeeper {
// Update data in the database
for user_id in updated_users {
self.dbm.lock().unwrap().update_user(
user_id,
*user_id,
self.registered_users.borrow().get(user_id).unwrap(),
);
}
@ -272,7 +267,7 @@ impl chain::Listen for Gatekeeper {
fn block_connected(&self, block: &bitcoin::Block, height: u32) {
// Expired user deletion is delayed. Users are deleted when their subscription is outdated, not expired.
log::info!("New block received: {}", block.block_hash());
let outdated_users = self.update_outdated_users_cache(&height);
let outdated_users = self.update_outdated_users_cache(height);
for user_id in outdated_users.keys() {
self.registered_users.borrow_mut().remove(user_id);
@ -330,7 +325,7 @@ mod tests {
// Last, let's add the user to the Gatekeeper and try again.
let user_id = UserId(user_pk);
gatekeeper.add_update_user(&user_id).unwrap();
gatekeeper.add_update_user(user_id).unwrap();
assert_eq!(
gatekeeper.authenticate_user(message, &signature),
Ok(user_id)
@ -349,17 +344,17 @@ mod tests {
// Let's start by adding new user
let user_id = get_random_user_id();
let receipt = gatekeeper.add_update_user(&user_id).unwrap();
let receipt = gatekeeper.add_update_user(user_id).unwrap();
// The data should have been also added to the database
assert_eq!(
dbm.lock().unwrap().load_user(&user_id).unwrap(),
dbm.lock().unwrap().load_user(user_id).unwrap(),
UserInfo::new(receipt.available_slots(), receipt.subscription_expiry())
);
// Let generate a new block and add the user again to check that both the slots and expiry are updated.
chain.generate_with_txs(Vec::new());
gatekeeper.last_known_block_header = chain.tip();
let updated_receipt = gatekeeper.add_update_user(&user_id).unwrap();
let updated_receipt = gatekeeper.add_update_user(user_id).unwrap();
assert_eq!(
updated_receipt.available_slots(),
@ -372,7 +367,7 @@ mod tests {
// Data in the database should have been updated too
assert_eq!(
dbm.lock().unwrap().load_user(&user_id).unwrap(),
dbm.lock().unwrap().load_user(user_id).unwrap(),
UserInfo::new(
updated_receipt.available_slots(),
updated_receipt.subscription_expiry()
@ -388,13 +383,13 @@ mod tests {
.available_slots = u32::MAX;
assert!(matches!(
gatekeeper.add_update_user(&user_id),
gatekeeper.add_update_user(user_id),
Err(MaxSlotsReached)
));
// Data in the database remains untouched
assert_eq!(
dbm.lock().unwrap().load_user(&user_id).unwrap(),
dbm.lock().unwrap().load_user(user_id).unwrap(),
UserInfo::new(
updated_receipt.available_slots(),
updated_receipt.subscription_expiry()
@ -414,7 +409,7 @@ mod tests {
// Let's first add the a user to the Gatekeeper (inputs are always sanitized here, so we don't need tests for non-registered users)
let user_id = get_random_user_id();
gatekeeper.add_update_user(&user_id).unwrap();
gatekeeper.add_update_user(user_id).unwrap();
// Now let's add a new appointment
let slots_before = gatekeeper
@ -425,7 +420,7 @@ mod tests {
.available_slots;
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
let available_slots = gatekeeper
.add_update_appointment(&user_id, uuid, &appointment)
.add_update_appointment(user_id, uuid, &appointment)
.unwrap();
assert!(gatekeeper.registered_users.borrow()[&user_id]
@ -435,54 +430,54 @@ mod tests {
// Slots should have been updated in the database too. Notice the appointment won't be there yet
// given the Watcher is responsible for adding it, and it will do so after calling this method
let mut loaded_user = dbm.lock().unwrap().load_user(&user_id).unwrap();
let mut loaded_user = dbm.lock().unwrap().load_user(user_id).unwrap();
assert_eq!(loaded_user.available_slots, available_slots);
// Adding the exact same appointment should leave the slots count unchanged
let mut updated_slot_count = gatekeeper
.add_update_appointment(&user_id, uuid, &appointment)
.add_update_appointment(user_id, uuid, &appointment)
.unwrap();
assert!(gatekeeper.registered_users.borrow()[&user_id]
.appointments
.contains_key(&uuid));
assert_eq!(updated_slot_count, available_slots);
loaded_user = dbm.lock().unwrap().load_user(&user_id).unwrap();
loaded_user = dbm.lock().unwrap().load_user(user_id).unwrap();
assert_eq!(loaded_user.available_slots, updated_slot_count);
// If we add an update to an existing appointment with a bigger data blob (modulo ENCRYPTED_BLOB_MAX_SIZE), additional slots should be taken
let mut bigger_appointment = appointment.clone();
bigger_appointment.inner.encrypted_blob = get_random_bytes(ENCRYPTED_BLOB_MAX_SIZE + 1);
updated_slot_count = gatekeeper
.add_update_appointment(&user_id, uuid, &bigger_appointment)
.add_update_appointment(user_id, uuid, &bigger_appointment)
.unwrap();
assert!(gatekeeper.registered_users.borrow()[&user_id]
.appointments
.contains_key(&uuid));
assert_eq!(updated_slot_count, available_slots - 1);
loaded_user = dbm.lock().unwrap().load_user(&user_id).unwrap();
loaded_user = dbm.lock().unwrap().load_user(user_id).unwrap();
assert_eq!(loaded_user.available_slots, updated_slot_count);
// Adding back a smaller update (modulo ENCRYPTED_BLOB_MAX_SIZE) should reduce the count
updated_slot_count = gatekeeper
.add_update_appointment(&user_id, uuid, &appointment)
.add_update_appointment(user_id, uuid, &appointment)
.unwrap();
assert!(gatekeeper.registered_users.borrow()[&user_id]
.appointments
.contains_key(&uuid));
assert_eq!(updated_slot_count, available_slots);
loaded_user = dbm.lock().unwrap().load_user(&user_id).unwrap();
loaded_user = dbm.lock().unwrap().load_user(user_id).unwrap();
assert_eq!(loaded_user.available_slots, updated_slot_count);
// Adding an appointment with a different uuid should not count as an update
let new_uuid = generate_uuid();
updated_slot_count = gatekeeper
.add_update_appointment(&user_id, new_uuid, &appointment)
.add_update_appointment(user_id, new_uuid, &appointment)
.unwrap();
assert!(gatekeeper.registered_users.borrow()[&user_id]
.appointments
.contains_key(&new_uuid));
assert_eq!(updated_slot_count, available_slots - 1);
loaded_user = dbm.lock().unwrap().load_user(&user_id).unwrap();
loaded_user = dbm.lock().unwrap().load_user(user_id).unwrap();
assert_eq!(loaded_user.available_slots, updated_slot_count);
// Finally, trying to add an appointment when the user has no enough slots should fail
@ -493,11 +488,11 @@ mod tests {
.unwrap()
.available_slots = 0;
assert!(matches!(
gatekeeper.add_update_appointment(&user_id, generate_uuid(), &appointment),
gatekeeper.add_update_appointment(user_id, generate_uuid(), &appointment),
Err(NotEnoughSlots)
));
// The entry in the database should remain unchanged in this case
loaded_user = dbm.lock().unwrap().load_user(&user_id).unwrap();
loaded_user = dbm.lock().unwrap().load_user(user_id).unwrap();
assert_eq!(loaded_user.available_slots, updated_slot_count);
}
@ -512,14 +507,14 @@ mod tests {
// If the user is not registered, querying for a subscription expiry check should return an error
assert!(matches!(
gatekeeper.has_subscription_expired(&user_id),
gatekeeper.has_subscription_expired(user_id),
Err(AuthenticationFailure { .. })
));
// If the user is registered and the subscription is active we should get (false, expiry)
gatekeeper.add_update_user(&user_id).unwrap();
gatekeeper.add_update_user(user_id).unwrap();
assert_eq!(
gatekeeper.has_subscription_expired(&user_id),
gatekeeper.has_subscription_expired(user_id),
Ok((false, DURATION + START_HEIGHT as u32))
);
@ -532,7 +527,7 @@ mod tests {
.unwrap()
.subscription_expiry = expiry;
assert_eq!(
gatekeeper.has_subscription_expired(&user_id),
gatekeeper.has_subscription_expired(user_id),
Ok((true, expiry))
);
}
@ -547,18 +542,18 @@ mod tests {
// Initially, the outdated_users_cache is empty, so querying any block height should return an empty map
for i in 0..start_height {
assert_eq!(gatekeeper.get_outdated_users(&i).len(), 0);
assert_eq!(gatekeeper.get_outdated_users(i).len(), 0);
}
// Adding a user whose subscription is outdated should return an entry
let user_id = get_random_user_id();
gatekeeper.add_update_user(&user_id).unwrap();
gatekeeper.add_update_user(user_id).unwrap();
// Add also an appointment so we can check the returned data
let appointment = generate_dummy_appointment(None);
let uuid = generate_uuid();
gatekeeper
.add_update_appointment(&user_id, uuid, &appointment)
.add_update_appointment(user_id, uuid, &appointment)
.unwrap();
// Check that data is not in the cache before querying
@ -571,7 +566,7 @@ mod tests {
.unwrap()
.subscription_expiry = START_HEIGHT as u32;
let outdated_users = gatekeeper.get_outdated_users(&start_height);
let outdated_users = gatekeeper.get_outdated_users(start_height);
assert_eq!(outdated_users.len(), 1);
assert_eq!(outdated_users[&user_id], Vec::from([uuid]));
@ -582,10 +577,7 @@ mod tests {
gatekeeper.outdated_users_cache.borrow().get(&target_height),
None
);
assert_eq!(
gatekeeper.get_outdated_users(&target_height),
HashMap::new()
);
assert_eq!(gatekeeper.get_outdated_users(target_height), HashMap::new());
let mut hm = HashMap::new();
hm.insert(user_id, Vec::from([uuid]));
@ -593,7 +585,7 @@ mod tests {
.outdated_users_cache
.borrow_mut()
.insert(target_height, hm.clone());
assert_eq!(gatekeeper.get_outdated_users(&start_height), hm);
assert_eq!(gatekeeper.get_outdated_users(start_height), hm);
}
#[test]
@ -608,14 +600,14 @@ mod tests {
// If there are no outdated users, there cannot be outdated appointments
for i in 0..start_height {
assert_eq!(gatekeeper.get_outdated_appointments(&i).len(), 0);
assert_eq!(gatekeeper.get_outdated_appointments(i).len(), 0);
}
// Adding data about different users and appointments should return a flattened list of appointments
let user1_id = get_random_user_id();
let user2_id = get_random_user_id();
gatekeeper.add_update_user(&user1_id).unwrap();
gatekeeper.add_update_user(&user2_id).unwrap();
gatekeeper.add_update_user(user1_id).unwrap();
gatekeeper.add_update_user(user2_id).unwrap();
// Manually set the user expiry for the test
gatekeeper
@ -637,13 +629,13 @@ mod tests {
let appointment = generate_dummy_appointment(None);
gatekeeper
.add_update_appointment(&user1_id, uuid1, &appointment)
.add_update_appointment(user1_id, uuid1, &appointment)
.unwrap();
gatekeeper
.add_update_appointment(&user2_id, uuid2, &appointment)
.add_update_appointment(user2_id, uuid2, &appointment)
.unwrap();
let outdated_appointments = gatekeeper.get_outdated_appointments(&start_height);
let outdated_appointments = gatekeeper.get_outdated_appointments(start_height);
assert_eq!(outdated_appointments.len(), 2);
assert!(outdated_appointments.contains(&uuid1));
assert!(outdated_appointments.contains(&uuid2));
@ -662,7 +654,7 @@ mod tests {
// If there's outdated data to be added and there's room in the cache, the data will be added
let user_id = get_random_user_id();
gatekeeper.add_update_user(&user_id).unwrap();
gatekeeper.add_update_user(user_id).unwrap();
gatekeeper
.registered_users
.borrow_mut()
@ -671,11 +663,11 @@ mod tests {
.subscription_expiry = start_height - EXPIRY_DELTA - 1;
assert_eq!(gatekeeper.outdated_users_cache.borrow().len(), 0);
gatekeeper.update_outdated_users_cache(&(start_height - 1));
gatekeeper.update_outdated_users_cache(start_height - 1);
assert_eq!(gatekeeper.outdated_users_cache.borrow().len(), 1);
// If the cache has room and there's no data to add, an empty entry will be added
gatekeeper.update_outdated_users_cache(&start_height);
gatekeeper.update_outdated_users_cache(start_height);
assert_eq!(gatekeeper.outdated_users_cache.borrow().len(), 2);
assert_eq!(
gatekeeper.outdated_users_cache.borrow()[&(start_height)],
@ -684,7 +676,7 @@ mod tests {
// Adding data (even empty) to the cache up to it's limit should remove the first element
for i in start_height + 1..start_height + OUTDATED_USERS_CACHE_SIZE_BLOCKS as u32 - 1 {
gatekeeper.update_outdated_users_cache(&i);
gatekeeper.update_outdated_users_cache(i);
}
// Check the first key is still there and that the user can still be found in the database
@ -697,13 +689,13 @@ mod tests {
.borrow()
.contains_key(&(start_height - 1)));
assert!(matches!(
dbm.lock().unwrap().load_user(&user_id),
dbm.lock().unwrap().load_user(user_id),
Ok(UserInfo { .. })
));
// Add one more block and check again. Data should have been removed from the cache and the database
gatekeeper.update_outdated_users_cache(
&(start_height + OUTDATED_USERS_CACHE_SIZE_BLOCKS as u32 - 1),
start_height + OUTDATED_USERS_CACHE_SIZE_BLOCKS as u32 - 1,
);
assert_eq!(
gatekeeper.outdated_users_cache.borrow().len(),
@ -713,7 +705,7 @@ mod tests {
.outdated_users_cache
.borrow()
.contains_key(&(start_height - 1)));
assert!(matches!(dbm.lock().unwrap().load_user(&user_id), Err(..)));
assert!(matches!(dbm.lock().unwrap().load_user(user_id), Err(..)));
}
#[test]
@ -730,7 +722,7 @@ mod tests {
for i in 1..11 {
let user_id = get_random_user_id();
let uuid = generate_uuid();
all_appointments.insert(uuid, user_id.clone());
all_appointments.insert(uuid, user_id);
if i % 2 == 0 {
to_be_deleted.insert(uuid, user_id);
@ -746,9 +738,9 @@ mod tests {
// If there's matching data in the gatekeeper it should be deleted
for (uuid, user_id) in to_be_deleted.iter() {
gatekeeper.add_update_user(&user_id).unwrap();
gatekeeper.add_update_user(*user_id).unwrap();
gatekeeper
.add_update_appointment(&user_id, *uuid, &generate_dummy_appointment(None))
.add_update_appointment(*user_id, *uuid, &generate_dummy_appointment(None))
.unwrap();
}
@ -769,7 +761,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.load_user(user_id)
.load_user(*user_id)
.unwrap()
.available_slots,
gatekeeper.subscription_slots
@ -782,13 +774,13 @@ mod tests {
// And after
gatekeeper.delete_appointments(&all_appointments);
for (uuid, user_id) in to_be_deleted.iter() {
assert!(!gatekeeper.registered_users.borrow()[user_id]
assert!(!gatekeeper.registered_users.borrow()[&user_id]
.appointments
.contains_key(uuid));
// The slot count is back to default
assert_eq!(
gatekeeper.registered_users.borrow()[user_id].available_slots,
gatekeeper.registered_users.borrow()[&user_id].available_slots,
gatekeeper.subscription_slots
);
assert_eq!(
@ -796,7 +788,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.load_user(user_id)
.load_user(*user_id)
.unwrap()
.available_slots,
gatekeeper.subscription_slots
@ -840,7 +832,7 @@ mod tests {
last_height += 1;
for user in vec![user1_id, user2_id, user3_id] {
gatekeeper.add_update_user(&user).unwrap();
gatekeeper.add_update_user(user).unwrap();
gatekeeper
.registered_users
.borrow_mut()
@ -859,7 +851,7 @@ mod tests {
// Data is still in the database since the user is in the cache
assert!(matches!(
dbm.lock().unwrap().load_user(&user),
dbm.lock().unwrap().load_user(user),
Ok(UserInfo { .. })
));
}
@ -872,7 +864,7 @@ mod tests {
for user in vec![user1_id, user2_id, user3_id] {
assert!(matches!(
dbm.lock().unwrap().load_user(&user),
dbm.lock().unwrap().load_user(user),
Err(DBError::NotFound)
));
}

View file

@ -23,7 +23,7 @@ use teos_common::cryptography::get_random_keypair;
async fn get_last_n_blocks<B, T>(
poller: &mut ChainPoller<B, T>,
tip: ValidatedBlockHeader,
mut last_known_block: ValidatedBlockHeader,
n: usize,
) -> Vec<ValidatedBlock>
where
@ -31,7 +31,6 @@ where
T: BlockSource,
{
let mut last_n_blocks = Vec::new();
let mut last_known_block = tip;
for _ in 0..n {
let block = poller.fetch_block(&last_known_block).await.unwrap();
last_known_block = poller
@ -96,10 +95,10 @@ pub async fn main() {
// Initialize our bitcoind client
let bitcoin_cli = match BitcoindClient::new(
conf.btc_rpc_connect.clone(),
&conf.btc_rpc_connect,
conf.btc_rpc_port,
conf.btc_rpc_user.clone(),
conf.btc_rpc_password.clone(),
&conf.btc_rpc_user,
&conf.btc_rpc_password,
)
.await
{
@ -120,7 +119,7 @@ pub async fn main() {
let rpc = Arc::new(
Client::new(
format!("{}{}:{}", schema, conf.btc_rpc_connect, conf.btc_rpc_port).to_string(),
Auth::UserPass(conf.btc_rpc_user, conf.btc_rpc_password),
Auth::UserPass(conf.btc_rpc_user.clone(), conf.btc_rpc_password.clone()),
)
.unwrap(),
);

View file

@ -40,7 +40,7 @@ impl TransactionTracker {
Self {
locator: breach.locator,
dispute_tx: breach.dispute_tx,
penalty_tx: breach.penalty_tx.clone(),
penalty_tx: breach.penalty_tx,
user_id,
}
}
@ -84,7 +84,7 @@ impl<'a> Responder<'a> {
missed_confirmations,
dbm,
gatekeeper,
last_known_block_header: RefCell::new(last_known_block_header.deref().clone()),
last_known_block_header: RefCell::new(*last_known_block_header.deref()),
}
}
@ -110,7 +110,7 @@ impl<'a> Responder<'a> {
confirmations: u32,
) {
let penalty_txid = breach.penalty_tx.txid();
let tracker = TransactionTracker::new(breach.clone(), user_id);
let tracker = TransactionTracker::new(breach, user_id);
self.trackers
.borrow_mut()
@ -129,27 +129,27 @@ impl<'a> Responder<'a> {
if !self
.unconfirmed_txs
.borrow()
.contains(&breach.penalty_tx.txid())
.contains(&tracker.penalty_tx.txid())
&& confirmations == 0
{
self.unconfirmed_txs
.borrow_mut()
.insert(breach.penalty_tx.txid());
.insert(tracker.penalty_tx.txid());
}
self.dbm
.lock()
.unwrap()
.store_tracker(&uuid, &tracker)
.store_tracker(uuid, &tracker)
.unwrap();
log::info!("New tracker added (uuid={}).", uuid);
}
pub fn has_tracker(&self, uuid: &UUID) -> bool {
pub fn has_tracker(&self, uuid: UUID) -> bool {
// Has tracker should return true as long as the given tracker is hold by the Responder.
// If the tracker is partially kept, the function will log and the return will be false.
// This may point out that some partial data deletion is happening, which must be fixed.
self.trackers.borrow().get(uuid).map_or(false, |tracker| {
self.trackers.borrow().get(&uuid).map_or(false, |tracker| {
self.tx_tracker_map
.borrow()
.get(&tracker.penalty_txid)
@ -165,9 +165,9 @@ impl<'a> Responder<'a> {
})
}
pub fn get_tracker(&self, uuid: &UUID) -> Option<TransactionTracker> {
pub fn get_tracker(&self, uuid: UUID) -> Option<TransactionTracker> {
if self.trackers.borrow().contains_key(&uuid) {
self.dbm.lock().unwrap().load_tracker(&uuid).ok()
self.dbm.lock().unwrap().load_tracker(uuid).ok()
} else {
None
}
@ -188,7 +188,7 @@ impl<'a> Responder<'a> {
match missed_confirmations.get_mut(txid) {
Some(x) => *x += 1,
None => {
missed_confirmations.insert(txid.clone(), 1);
missed_confirmations.insert(*txid, 1);
}
}
log::info!(
@ -206,7 +206,7 @@ impl<'a> Responder<'a> {
for (txid, missed_conf) in self.missed_confirmations.borrow().iter() {
if missed_conf >= &CONFIRMATIONS_BEFORE_RETRY {
for uuid in self.tx_tracker_map.borrow().get(txid).unwrap() {
tracker = self.dbm.lock().unwrap().load_tracker(uuid).unwrap();
tracker = self.dbm.lock().unwrap().load_tracker(*uuid).unwrap();
tx_to_rebroadcast.push(tracker.penalty_tx)
}
}
@ -228,7 +228,7 @@ impl<'a> Responder<'a> {
.await
.map(|confirmations| {
if confirmations > constants::IRREVOCABLY_RESOLVED {
completed_trackers.insert(uuid.clone());
completed_trackers.insert(*uuid);
}
});
}
@ -237,13 +237,13 @@ impl<'a> Responder<'a> {
completed_trackers
}
fn get_outdated_trackers(&self, block_height: &u32) -> HashSet<UUID> {
fn get_outdated_trackers(&self, block_height: u32) -> HashSet<UUID> {
let mut outdated_trackers = HashSet::new();
let trackers: HashSet<UUID> = self.trackers.borrow().keys().cloned().collect();
for uuid in self
.gatekeeper
.get_outdated_appointments(&block_height)
.get_outdated_appointments(block_height)
.intersection(&trackers)
{
if self
@ -251,7 +251,7 @@ impl<'a> Responder<'a> {
.borrow()
.contains(&self.trackers.borrow()[&uuid].penalty_txid)
{
outdated_trackers.insert(uuid.clone());
outdated_trackers.insert(*uuid);
}
}
@ -349,11 +349,11 @@ impl<'a> Listen for Responder<'a> {
if self.trackers.borrow().len() > 0 {
let completed_trackers = block_on(self.get_completed_trackers());
let outdated_trackers = self.get_outdated_trackers(&height);
let outdated_trackers = self.get_outdated_trackers(height);
let trackers_to_delete_gk = completed_trackers
.iter()
.map(|uuid| (uuid.clone(), self.trackers.borrow()[uuid].user_id))
.map(|uuid| (*uuid, self.trackers.borrow()[uuid].user_id))
.collect();
self.check_confirmations(&block.txdata);
@ -421,7 +421,7 @@ mod tests {
let user_id = get_random_user_id();
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), &uuid, &appointment);
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), uuid, &appointment);
let breach = get_random_breach_from_locator(appointment.locator());
let penalty_txid = breach.penalty_tx.txid();
@ -475,7 +475,7 @@ mod tests {
// Add the necessary FKs in the database
let user_id = get_random_user_id();
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), &uuid, &appointment);
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), uuid, &appointment);
let mut breach = get_random_breach_from_locator(appointment.locator());
responder.add_tracker(uuid, breach.clone(), user_id, 0);
@ -493,7 +493,7 @@ mod tests {
.contains(&breach.penalty_tx.txid()));
// Check that the data is also in the database
assert_eq!(
dbm.lock().unwrap().load_tracker(&uuid).unwrap(),
dbm.lock().unwrap().load_tracker(uuid).unwrap(),
TransactionTracker::new(breach, user_id)
);
@ -506,7 +506,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.store_appointment(&uuid, &appointment)
.store_appointment(uuid, &appointment)
.unwrap();
responder.add_tracker(uuid, breach.clone(), user_id, 1);
@ -525,7 +525,7 @@ mod tests {
.borrow()
.contains(&breach.penalty_tx.txid()));
assert_eq!(
dbm.lock().unwrap().load_tracker(&uuid).unwrap(),
dbm.lock().unwrap().load_tracker(uuid).unwrap(),
TransactionTracker::new(breach.clone(), user_id)
);
@ -535,7 +535,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.store_appointment(&uuid, &appointment)
.store_appointment(uuid, &appointment)
.unwrap();
responder.add_tracker(uuid, breach.clone(), user_id, 1);
@ -550,7 +550,7 @@ mod tests {
2
);
assert_eq!(
dbm.lock().unwrap().load_tracker(&uuid).unwrap(),
dbm.lock().unwrap().load_tracker(uuid).unwrap(),
TransactionTracker::new(breach, user_id)
);
}
@ -569,16 +569,16 @@ mod tests {
// Add a new tracker
let user_id = get_random_user_id();
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), &uuid, &appointment);
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), uuid, &appointment);
let breach = get_random_breach_from_locator(appointment.locator());
responder.add_tracker(uuid, breach.clone(), user_id, 0);
assert!(responder.has_tracker(&uuid));
assert!(responder.has_tracker(uuid));
// Delete the tracker and check again
responder.delete_trackers(HashSet::from_iter([uuid]), false);
assert!(!responder.has_tracker(&uuid));
assert!(!responder.has_tracker(uuid));
}
#[test]
@ -592,20 +592,20 @@ mod tests {
// Store the user and the appointment in the database so we can add the tracker later on (due to FK restrictions)
let user_id = get_random_user_id();
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), &uuid, &appointment);
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), uuid, &appointment);
// Data should not be there before adding it
assert_eq!(responder.get_tracker(&uuid), None);
assert_eq!(responder.get_tracker(uuid), None);
// Data should be there now
let breach = get_random_breach_from_locator(appointment.locator());
let tracker = TransactionTracker::new(breach.clone(), user_id);
responder.add_tracker(uuid, breach, user_id, 0);
assert_eq!(responder.get_tracker(&uuid).unwrap(), tracker);
assert_eq!(responder.get_tracker(uuid).unwrap(), tracker);
// After deleting the data it should be gone
responder.delete_trackers(HashSet::from_iter([uuid]), false);
assert_eq!(responder.get_tracker(&uuid), None);
assert_eq!(responder.get_tracker(uuid), None);
}
#[test]
@ -669,7 +669,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.store_user(&user_id, &UserInfo::new(21, 42))
.store_user(user_id, &UserInfo::new(21, 42))
.unwrap();
// Transactions are flagged to be rebroadcast when they've missed CONFIRMATIONS_BEFORE_RETRY confirmations
@ -682,7 +682,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.store_appointment(&uuid, &appointment)
.store_appointment(uuid, &appointment)
.unwrap();
// Create a breach and add it, manually setting the missed confirmation count
@ -718,7 +718,7 @@ mod tests {
let user_id = get_random_user_id();
let (uuid, appointment) = generate_dummy_appointment_with_user(user_id, None);
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), &uuid, &appointment);
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), uuid, &appointment);
// Let's add a tracker first
let breach = get_random_breach_from_locator(appointment.locator());
@ -766,7 +766,7 @@ mod tests {
// If data is not in the unconfirmed_transaction it won't be returned
assert_eq!(
responder.get_outdated_trackers(&target_block_height),
responder.get_outdated_trackers(target_block_height),
HashSet::new(),
);
@ -792,7 +792,7 @@ mod tests {
// Check the expected data is there
assert_eq!(
responder.get_outdated_trackers(&target_block_height),
responder.get_outdated_trackers(target_block_height),
target_uuids
);
}
@ -810,7 +810,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.store_user(&user_id, &UserInfo::new(21, 42))
.store_user(user_id, &UserInfo::new(21, 42))
.unwrap();
// Transactions are rebroadcast once they hit CONFIRMATIONS_BEFORE_RETRY
@ -825,7 +825,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.store_appointment(&uuid, &appointment)
.store_appointment(uuid, &appointment)
.unwrap();
let breach = get_random_breach_from_locator(appointment.locator());
@ -886,7 +886,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.store_user(&user_id, &UserInfo::new(21, 42))
.store_user(user_id, &UserInfo::new(21, 42))
.unwrap();
// Delete trackers removes data from the trackers, tx_tracker_map maps, the database (and unconfirmed_txs if the data is outdated)
@ -904,7 +904,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.store_appointment(&uuid, &appointment)
.store_appointment(uuid, &appointment)
.unwrap();
let breach = get_random_breach_from_locator(appointment.locator());
@ -922,8 +922,8 @@ mod tests {
txs_with_multiple_uuids.insert(breach.penalty_tx.txid());
}
all_trackers.insert(uuid.clone());
uuid_txid_map.insert(uuid.clone(), breach.penalty_tx.txid());
all_trackers.insert(uuid);
uuid_txid_map.insert(uuid, breach.penalty_tx.txid());
// Add some trackers to be deleted
if i % 2 == 0 {
@ -939,7 +939,7 @@ mod tests {
if target_trackers.contains(&uuid) {
assert!(!responder.trackers.borrow().contains_key(&uuid));
assert!(matches!(
dbm.lock().unwrap().load_tracker(&uuid),
dbm.lock().unwrap().load_tracker(uuid),
Err(DBError::NotFound)
));
let penalty_txid = &uuid_txid_map[&uuid];
@ -966,7 +966,7 @@ mod tests {
.borrow()
.contains_key(&uuid_txid_map[&uuid]));
assert!(matches!(
dbm.lock().unwrap().load_tracker(&uuid),
dbm.lock().unwrap().load_tracker(uuid),
Ok(TransactionTracker { .. })
));
}
@ -1025,7 +1025,7 @@ mod tests {
for _ in 2..23 {
let user_id = get_random_user_id();
gk.add_update_user(&user_id).unwrap();
gk.add_update_user(user_id).unwrap();
users.push(user_id);
}
@ -1041,7 +1041,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.store_appointment(&uuid, &appointment)
.store_appointment(uuid, &appointment)
.unwrap();
let breach = get_random_breach_from_locator(appointment.locator());
@ -1076,12 +1076,12 @@ mod tests {
.dbm
.lock()
.unwrap()
.store_appointment(&uuid, &appointment)
.store_appointment(*uuid, &appointment)
.unwrap();
let breach = get_random_breach_from_locator(appointment.locator());
penalties.push(breach.penalty_tx.txid());
responder.add_tracker(uuid.clone(), breach, user_id, 0);
responder.add_tracker(*uuid, breach, user_id, 0);
}
outdated_users.insert(user_id, pair.clone());
@ -1094,7 +1094,7 @@ mod tests {
// CONFIRMATIONS SETUP
let standalone_user_id = get_random_user_id();
gk.add_update_user(&standalone_user_id).unwrap();
gk.add_update_user(standalone_user_id).unwrap();
let mut transactions = Vec::new();
let mut confirmed_txs = Vec::new();
@ -1106,7 +1106,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.store_appointment(&uuid, &appointment)
.store_appointment(uuid, &appointment)
.unwrap();
let breach = get_random_breach_from_locator(appointment.locator());
@ -1129,7 +1129,7 @@ mod tests {
.dbm
.lock()
.unwrap()
.store_appointment(&uuid, &appointment)
.store_appointment(uuid, &appointment)
.unwrap();
let breach_rebroadcast = get_random_breach_from_locator(appointment.locator());

View file

@ -104,12 +104,7 @@ impl Blockchain {
};
for _ in 1..=height {
let mut txs = Vec::new();
for _ in 0..tx_count {
txs.push(get_random_tx());
}
self.generate_with_txs(txs);
self.generate_with_txs((0..tx_count).map(|_| get_random_tx()).collect());
}
self
@ -334,7 +329,7 @@ pub(crate) fn get_random_tx() -> Transaction {
pub(crate) fn generate_dummy_appointment(dispute_txid: Option<&Txid>) -> ExtendedAppointment {
let dispute_txid = match dispute_txid {
Some(l) => l.clone(),
Some(l) => *l,
None => {
let prev_txid_bytes = get_random_bytes(32);
Txid::from_slice(&prev_txid_bytes).unwrap()
@ -363,7 +358,7 @@ pub(crate) fn generate_dummy_appointment_with_user(
let mut app = generate_dummy_appointment(dispute_txid);
app.user_id = user_id;
(UUID::new(&app.locator(), &user_id), app)
(UUID::new(app.locator(), user_id), app)
}
pub fn get_random_breach() -> Breach {
@ -385,10 +380,10 @@ pub fn get_random_tracker(user_id: UserId) -> TransactionTracker {
TransactionTracker::new(breach, user_id)
}
pub fn store_appointment_and_fks_to_db(dbm: &DBM, uuid: &UUID, appointment: &ExtendedAppointment) {
dbm.store_user(&appointment.user_id, &UserInfo::new(21, 42))
pub fn store_appointment_and_fks_to_db(dbm: &DBM, uuid: UUID, appointment: &ExtendedAppointment) {
dbm.store_user(appointment.user_id, &UserInfo::new(21, 42))
.unwrap();
dbm.store_appointment(&uuid, &appointment).unwrap();
dbm.store_appointment(uuid, &appointment).unwrap();
}
pub enum MockedServerQuery {

View file

@ -57,9 +57,9 @@ impl LocatorCache {
});
let mut locators = Vec::new();
for tx in block.txdata.clone() {
for tx in &block.txdata {
let locator = Locator::new(tx.txid());
cache.insert(locator, tx);
cache.insert(locator, tx.clone());
locators.push(locator);
}
@ -75,8 +75,8 @@ impl LocatorCache {
}
}
pub fn get_tx(&self, locator: &Locator) -> Option<&Transaction> {
self.cache.get(locator)
pub fn get_tx(&self, locator: Locator) -> Option<&Transaction> {
self.cache.get(&locator)
}
pub fn is_full(&self) -> bool {
@ -92,8 +92,8 @@ impl LocatorCache {
let mut locators = Vec::new();
for (locator, tx) in locator_tx_map {
self.cache.insert(locator.clone(), tx.clone());
locators.push(locator.clone());
self.cache.insert(*locator, tx.clone());
locators.push(*locator);
}
self.tx_in_block.insert(block_header.block_hash(), locators);
@ -205,13 +205,13 @@ impl<'a> Watcher<'a> {
locator_cache,
responder,
gatekeeper,
last_known_block_header: RefCell::new(last_known_block_header.deref().clone()),
last_known_block_header: RefCell::new(*last_known_block_header.deref()),
signing_key,
dbm,
}
}
pub fn register(&mut self, user_id: &UserId) -> Result<RegistrationReceipt, MaxSlotsReached> {
pub fn register(&mut self, user_id: UserId) -> Result<RegistrationReceipt, MaxSlotsReached> {
let mut receipt = self.gatekeeper.add_update_user(user_id)?;
receipt.sign(&self.signing_key);
@ -229,7 +229,7 @@ impl<'a> Watcher<'a> {
.map_err(|_| AddAppointmentFailure::AuthenticationFailure)?;
let (has_subscription_expired, expiry) =
self.gatekeeper.has_subscription_expired(&user_id).unwrap();
self.gatekeeper.has_subscription_expired(user_id).unwrap();
if has_subscription_expired {
return Err(AddAppointmentFailure::SubscriptionExpired(expiry));
@ -242,20 +242,20 @@ impl<'a> Watcher<'a> {
self.last_known_block_header.borrow().height,
);
let uuid = UUID::new(&extended_appointment.locator(), &user_id);
let uuid = UUID::new(extended_appointment.locator(), user_id);
if self.responder.has_tracker(&uuid) {
if self.responder.has_tracker(uuid) {
log::info!("Tracker for {} already found in Responder", uuid);
return Err(AddAppointmentFailure::AlreadyTriggered);
}
let available_slots = self
.gatekeeper
.add_update_appointment(&user_id, uuid, &extended_appointment)
.add_update_appointment(user_id, uuid, &extended_appointment)
.map_err(|_| AddAppointmentFailure::NotEnoughSlots)?;
let locator = extended_appointment.locator();
match self.locator_cache.borrow().get_tx(&locator) {
match self.locator_cache.borrow().get_tx(locator) {
// Appointments that were triggered in blocks held in the cache
Some(dispute_tx) => {
log::info!("Trigger for locator {} found in cache", locator);
@ -269,7 +269,7 @@ impl<'a> Watcher<'a> {
self.dbm
.lock()
.unwrap()
.store_appointment(&uuid, &extended_appointment)
.store_appointment(uuid, &extended_appointment)
.unwrap();
let breach = Breach::new(locator, dispute_tx.clone(), penalty_tx);
@ -285,7 +285,7 @@ impl<'a> Watcher<'a> {
receipt.reason()
);
self.dbm.lock().unwrap().remove_appointment(&uuid);
self.dbm.lock().unwrap().remove_appointment(uuid);
}
}
@ -318,14 +318,14 @@ impl<'a> Watcher<'a> {
self.dbm
.lock()
.unwrap()
.store_appointment(&uuid, &extended_appointment)
.store_appointment(uuid, &extended_appointment)
.unwrap();
} else {
log::debug!("Update received for {}, locator map not modified", uuid);
self.dbm
.lock()
.unwrap()
.update_appointment(&uuid, &extended_appointment);
.update_appointment(uuid, &extended_appointment);
}
} else {
// New appointment
@ -336,7 +336,7 @@ impl<'a> Watcher<'a> {
self.dbm
.lock()
.unwrap()
.store_appointment(&uuid, &extended_appointment)
.store_appointment(uuid, &extended_appointment)
.unwrap();
}
}
@ -353,8 +353,8 @@ impl<'a> Watcher<'a> {
pub fn get_appointment(
&self,
locator: &Locator,
user_signature: &String,
locator: Locator,
user_signature: &str,
) -> Result<AppointmentInfo, GetAppointmentFailure> {
let message = format!("get appointment {}", locator);
@ -364,26 +364,26 @@ impl<'a> Watcher<'a> {
.map_err(|_| GetAppointmentFailure::AuthenticationFailure)?;
let (has_subscription_expired, expiry) =
self.gatekeeper.has_subscription_expired(&user_id).unwrap();
self.gatekeeper.has_subscription_expired(user_id).unwrap();
if has_subscription_expired {
return Err(GetAppointmentFailure::SubscriptionExpired(expiry));
}
let uuid = UUID::new(locator, &user_id);
let uuid = UUID::new(locator, user_id);
if self.appointments.borrow().contains_key(&uuid) {
Ok(AppointmentInfo::Appointment(
self.dbm
.lock()
.unwrap()
.load_appointment(&uuid)
.load_appointment(uuid)
.unwrap()
.inner,
))
} else {
self.responder
.get_tracker(&uuid)
.get_tracker(uuid)
.map(|tracker| AppointmentInfo::Tracker(tracker))
.ok_or({
log::info!("Cannot find {}", locator);
@ -402,7 +402,7 @@ impl<'a> Watcher<'a> {
for locator in local_set.intersection(&new_set) {
let (k, v) = locator_tx_map.get_key_value(locator).unwrap();
breaches.insert(k.clone(), v.clone());
breaches.insert(*k, v.clone());
}
if breaches.is_empty() {
@ -428,18 +428,12 @@ impl<'a> Watcher<'a> {
let mut decrypted_blobs: HashMap<Vec<u8>, Transaction> = HashMap::new();
for (locator, dispute_tx) in breaches.into_iter() {
for uuid in self
.locator_uuid_map
.borrow()
.get(&locator)
.unwrap()
.clone()
{
let appointment = self.dbm.lock().unwrap().load_appointment(&uuid).unwrap();
for uuid in self.locator_uuid_map.borrow().get(&locator).unwrap() {
let appointment = self.dbm.lock().unwrap().load_appointment(*uuid).unwrap();
match decrypted_blobs.get(appointment.encrypted_blob()) {
Some(penalty_tx) => {
valid_breaches.insert(
uuid,
*uuid,
Breach::new(locator, dispute_tx.clone(), penalty_tx.clone()),
);
}
@ -454,12 +448,12 @@ impl<'a> Watcher<'a> {
penalty_tx.clone(),
);
valid_breaches.insert(
uuid,
*uuid,
Breach::new(locator, dispute_tx.clone(), penalty_tx),
);
}
Err(e) => {
invalid_breaches.insert(uuid, e);
invalid_breaches.insert(*uuid, e);
}
}
}
@ -535,7 +529,7 @@ impl<'a> chain::Listen for Watcher<'a> {
if !self.appointments.borrow().is_empty() {
// Get a list of outdated appointments from the Gatekeeper. This appointments may be either in the Watcher
// or in the Responder.
let outdated_appointments = self.gatekeeper.get_outdated_appointments(&height);
let outdated_appointments = self.gatekeeper.get_outdated_appointments(height);
self.delete_appointments(outdated_appointments, true);
// Filter out those breaches that do not yield a valid transaction
@ -674,16 +668,16 @@ mod tests {
expected_slots: u32,
expiry: u32,
receipt: AppointmentReceipt,
expected_user_signature: &String,
tower_id: &UserId,
expected_user_signature: &str,
tower_id: UserId,
) {
assert_eq!(slots, expected_slots);
assert_eq!(expiry, START_HEIGHT as u32 + DURATION);
assert_eq!(receipt.start_block(), START_HEIGHT as u32);
assert_eq!(&receipt.user_signature(), expected_user_signature);
assert_eq!(receipt.user_signature(), expected_user_signature);
let recovered_pk =
cryptography::recover_pk(&receipt.serialize(), &receipt.signature().unwrap()).unwrap();
assert_eq!(&UserId(recovered_pk), tower_id);
assert_eq!(UserId(recovered_pk), tower_id);
}
#[tokio::test]
@ -712,9 +706,9 @@ mod tests {
let (_, user_pk) = get_random_keypair();
let user_id = UserId(user_pk);
let receipt = watcher.register(&user_id).unwrap();
let receipt = watcher.register(user_id).unwrap();
assert_eq!(receipt.user_id(), &user_id);
assert_eq!(receipt.user_id(), user_id);
assert_eq!(receipt.available_slots(), SLOTS);
assert_eq!(
receipt.subscription_expiry(),
@ -756,7 +750,7 @@ mod tests {
));
let (user_sk, user_pk) = get_random_keypair();
let user_id = UserId(user_pk);
watcher.register(&user_id).unwrap();
watcher.register(user_id).unwrap();
let appointment = generate_dummy_appointment(None).inner;
// Add the appointment for a new user (twice so we can check that updates work)
@ -767,13 +761,13 @@ mod tests {
.await
.unwrap();
assert_appointment_added(slots, SLOTS - 1, expiry, receipt, &user_sig, &tower_id);
assert_appointment_added(slots, SLOTS - 1, expiry, receipt, &user_sig, tower_id);
}
// Add the same appointment but for another user
let (user2_sk, user2_pk) = get_random_keypair();
let user2_id = UserId(user2_pk);
watcher.register(&user2_id).unwrap();
watcher.register(user2_id).unwrap();
let user2_sig = cryptography::sign(&appointment.serialize(), &user2_sk).unwrap();
let (receipt, slots, expiry) = watcher
@ -781,7 +775,7 @@ mod tests {
.await
.unwrap();
assert_appointment_added(slots, SLOTS - 1, expiry, receipt, &user2_sig, &tower_id);
assert_appointment_added(slots, SLOTS - 1, expiry, receipt, &user2_sig, tower_id);
// There should be now two appointments in the Watcher and the same locator should have two different uuids
assert_eq!(watcher.appointments.borrow().len(), 2);
@ -793,7 +787,7 @@ mod tests {
// Check data was added to the database
for uuid in watcher.appointments.borrow().keys() {
assert!(matches!(
dbm.lock().unwrap().load_appointment(&uuid),
dbm.lock().unwrap().load_appointment(*uuid),
Ok(ExtendedAppointment { .. })
));
}
@ -830,21 +824,21 @@ mod tests {
// The appointment should have been accepted, slots should have been decreased, and data should have been deleted from
// the Watcher's memory. Moreover, a new tracker should be found in the Responder
assert_appointment_added(slots, SLOTS - 3, expiry, receipt, &user_sig, &tower_id);
assert_appointment_added(slots, SLOTS - 3, expiry, receipt, &user_sig, tower_id);
assert_eq!(watcher.appointments.borrow().len(), 3);
assert!(!watcher
.locator_uuid_map
.borrow()
.contains_key(&appointment_in_cache.locator()));
assert!(watcher.responder.has_tracker(&uuid));
assert!(watcher.responder.has_tracker(uuid));
// Check data was added to the database
assert!(matches!(
dbm.lock().unwrap().load_appointment(&uuid),
dbm.lock().unwrap().load_appointment(uuid),
Ok(ExtendedAppointment { .. })
));
assert!(matches!(
dbm.lock().unwrap().load_tracker(&uuid),
dbm.lock().unwrap().load_tracker(uuid),
Ok(TransactionTracker { .. })
));
@ -861,16 +855,16 @@ mod tests {
.await
.unwrap();
assert_appointment_added(slots, SLOTS - 4, expiry, receipt, &user_sig, &tower_id);
assert_appointment_added(slots, SLOTS - 4, expiry, receipt, &user_sig, tower_id);
assert_eq!(watcher.appointments.borrow().len(), 3);
// Data should not be in the database
assert!(matches!(
dbm.lock().unwrap().load_appointment(&uuid),
dbm.lock().unwrap().load_appointment(uuid),
Err(DBError::NotFound)
));
assert!(matches!(
dbm.lock().unwrap().load_tracker(&uuid),
dbm.lock().unwrap().load_tracker(uuid),
Err(DBError::NotFound)
));
@ -888,12 +882,12 @@ mod tests {
.await
.unwrap();
assert_appointment_added(slots, SLOTS - 4, expiry, receipt, &user_sig, &tower_id);
assert_appointment_added(slots, SLOTS - 4, expiry, receipt, &user_sig, tower_id);
assert_eq!(watcher.appointments.borrow().len(), 3);
// Data should not be in the database
assert!(matches!(
dbm.lock().unwrap().load_appointment(&uuid),
dbm.lock().unwrap().load_appointment(uuid),
Err(DBError::NotFound)
));
@ -911,7 +905,7 @@ mod tests {
));
// Data should not be in the database
assert!(matches!(
dbm.lock().unwrap().load_appointment(&uuid),
dbm.lock().unwrap().load_appointment(uuid),
Err(DBError::NotFound)
));
@ -935,7 +929,7 @@ mod tests {
));
// Data should not be in the database
assert!(matches!(
dbm.lock().unwrap().load_appointment(&uuid),
dbm.lock().unwrap().load_appointment(uuid),
Err(DBError::NotFound)
));
@ -956,7 +950,7 @@ mod tests {
));
// Data should not be in the database
assert!(matches!(
dbm.lock().unwrap().load_appointment(&uuid),
dbm.lock().unwrap().load_appointment(uuid),
Err(DBError::NotFound)
));
}
@ -977,14 +971,14 @@ mod tests {
// If the user cannot be properly identified, the request will fail. This can be simulated by providing a wrong signature
let wrong_sig = String::from_utf8((0..65).collect()).unwrap();
assert!(matches!(
watcher.get_appointment(&appointment.locator, &wrong_sig),
watcher.get_appointment(appointment.locator, &wrong_sig),
Err(GetAppointmentFailure::AuthenticationFailure)
));
// If the user does exist and there's an appointment with the given locator belonging to him, it will be returned
let (user_sk, user_pk) = get_random_keypair();
let user_id = UserId(user_pk);
watcher.register(&user_id).unwrap();
watcher.register(user_id).unwrap();
watcher
.add_appointment(
appointment.clone(),
@ -996,7 +990,7 @@ mod tests {
let message = format!("get appointment {}", appointment.locator);
let signature = cryptography::sign(message.as_bytes(), &user_sk).unwrap();
let info = watcher
.get_appointment(&appointment.locator, &signature)
.get_appointment(appointment.locator, &signature)
.unwrap();
match info {
@ -1007,7 +1001,7 @@ mod tests {
// If the appointment is in the Responder (in the form of a Tracker), data should be also returned
// Remove the data from the Watcher memory first (data is kept in the db tho)
let uuid = UUID::new(&appointment.locator, &user_id);
let uuid = UUID::new(appointment.locator, user_id);
watcher.appointments.borrow_mut().remove(&uuid);
watcher
.locator_uuid_map
@ -1023,7 +1017,7 @@ mod tests {
let tracker_message = format!("get appointment {}", tracker.locator);
let tracker_signature = cryptography::sign(tracker_message.as_bytes(), &user_sk).unwrap();
let info = watcher
.get_appointment(&tracker.locator, &tracker_signature)
.get_appointment(tracker.locator, &tracker_signature)
.unwrap();
match info {
@ -1035,11 +1029,11 @@ mod tests {
// should be returned.
let (user2_sk, user2_pk) = get_random_keypair();
let user2_id = UserId(user2_pk);
watcher.register(&user2_id).unwrap();
watcher.register(user2_id).unwrap();
let signature2 = cryptography::sign(message.as_bytes(), &user2_sk).unwrap();
assert!(matches!(
watcher.get_appointment(&appointment.locator, &signature2),
watcher.get_appointment(appointment.locator, &signature2),
Err(GetAppointmentFailure::NotFound { .. })
));
@ -1053,7 +1047,7 @@ mod tests {
.subscription_expiry = START_HEIGHT as u32;
assert!(matches!(
watcher.get_appointment(&appointment.locator, &signature),
watcher.get_appointment(appointment.locator, &signature),
Err(GetAppointmentFailure::SubscriptionExpired { .. })
));
}
@ -1081,7 +1075,7 @@ mod tests {
watcher
.locator_uuid_map
.borrow_mut()
.insert(locator.clone(), HashSet::from_iter(vec![generate_uuid()]));
.insert(*locator, HashSet::from_iter(vec![generate_uuid()]));
}
}
@ -1140,10 +1134,10 @@ mod tests {
watcher
.locator_uuid_map
.borrow_mut()
.insert(locator.clone(), HashSet::from_iter(vec![uuid]));
.insert(*locator, HashSet::from_iter(vec![uuid]));
// Store data in the database (the user needs to be there as well since it is a FK for appointments)
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), &uuid, &appointment);
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), uuid, &appointment);
}
}
@ -1200,7 +1194,7 @@ mod tests {
.insert(appointment.locator(), HashSet::from_iter([uuid]));
// Add data to the database to check data deletion
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), &uuid, &appointment);
store_appointment_and_fks_to_db(&dbm.lock().unwrap(), uuid, &appointment);
// Make it so some of the locators have multiple associated uuids
if i % 3 == 0 {
@ -1232,7 +1226,7 @@ mod tests {
if target_appointments.contains(&uuid) {
assert!(!watcher.appointments.borrow().contains_key(&uuid));
assert!(matches!(
dbm.lock().unwrap().load_appointment(&uuid),
dbm.lock().unwrap().load_appointment(uuid),
Err(DBError::NotFound)
));
@ -1260,7 +1254,7 @@ mod tests {
.borrow()
.contains_key(&uuid_locator_map[&uuid]));
assert!(matches!(
dbm.lock().unwrap().load_appointment(&uuid),
dbm.lock().unwrap().load_appointment(uuid),
Ok(ExtendedAppointment { .. })
));
}
@ -1315,12 +1309,12 @@ mod tests {
let user_id = UserId(user_pk);
let (user2_sk, user2_pk) = get_random_keypair();
let user2_id = UserId(user2_pk);
watcher.register(&user_id).unwrap();
watcher.register(&user2_id).unwrap();
watcher.register(user_id).unwrap();
watcher.register(user2_id).unwrap();
let appointment = generate_dummy_appointment(None);
let uuid1 = UUID::new(&appointment.locator(), &user_id);
let uuid2 = UUID::new(&appointment.locator(), &user2_id);
let uuid1 = UUID::new(appointment.locator(), user_id);
let uuid2 = UUID::new(appointment.locator(), user2_id);
let user_sig = cryptography::sign(&appointment.inner.serialize(), &user_sk).unwrap();
watcher
@ -1361,7 +1355,7 @@ mod tests {
.appointments
.contains_key(&uuid1));
assert!(matches!(
dbm.lock().unwrap().load_appointment(&uuid1),
dbm.lock().unwrap().load_appointment(uuid1),
Err(DBError::NotFound)
));
@ -1371,7 +1365,7 @@ mod tests {
.appointments
.contains_key(&uuid2));
assert!(matches!(
dbm.lock().unwrap().load_appointment(&uuid2),
dbm.lock().unwrap().load_appointment(uuid2),
Ok(ExtendedAppointment { .. })
));
@ -1379,7 +1373,7 @@ mod tests {
let dispute_tx = get_random_tx();
let appointment = generate_dummy_appointment(Some(&dispute_tx.txid()));
let sig = cryptography::sign(&appointment.inner.serialize(), &user2_sk).unwrap();
let uuid = UUID::new(&appointment.locator(), &user2_id);
let uuid = UUID::new(appointment.locator(), user2_id);
watcher
.add_appointment(appointment.inner.clone(), sig)
.await
@ -1406,7 +1400,7 @@ mod tests {
//Both non-decryptable blobs and blobs with invalid transactions will yield an invalid trigger
appointment.inner.encrypted_blob.reverse();
let sig = cryptography::sign(&appointment.inner.serialize(), &user2_sk).unwrap();
let uuid = UUID::new(&appointment.locator(), &user2_id);
let uuid = UUID::new(appointment.locator(), user2_id);
watcher
.add_appointment(appointment.inner.clone(), sig)
.await
@ -1424,7 +1418,7 @@ mod tests {
.appointments
.contains_key(&uuid));
assert!(matches!(
dbm.lock().unwrap().load_appointment(&uuid),
dbm.lock().unwrap().load_appointment(uuid),
Err(DBError::NotFound)
));
}