From b5da110cbbed92ba64ebe22e8213d0f11078a8fc Mon Sep 17 00:00:00 2001 From: Sergi Delgado Segura Date: Mon, 18 Oct 2021 17:22:35 +0200 Subject: [PATCH] Removes JSON serde, moves slots computation logic to appointment.rs The JSON serialization logic was added to deal with data storage. Given won't be using LevelDB for this implementation, but a SQL database, all that serialization logic in unnecessary. --- teos-common/Cargo.toml | 2 - teos-common/src/appointment.rs | 66 +++++++-------------------- teos-common/src/lib.rs | 62 +++----------------------- teos/Cargo.toml | 1 - teos/src/extended_appointment.rs | 76 +++++--------------------------- teos/src/gatekeeper.rs | 20 +++------ 6 files changed, 39 insertions(+), 188 deletions(-) diff --git a/teos-common/Cargo.toml b/teos-common/Cargo.toml index e9c00a9..8435583 100644 --- a/teos-common/Cargo.toml +++ b/teos-common/Cargo.toml @@ -7,8 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serde = {version = "1.0.126", features = ["derive"]} -serde_json = "1.0" uuid = { version = "0.8", features = ["serde", "v4"] } hex = "0.4.3" diff --git a/teos-common/src/appointment.rs b/teos-common/src/appointment.rs index 548730c..da90ac2 100644 --- a/teos-common/src/appointment.rs +++ b/teos-common/src/appointment.rs @@ -1,11 +1,9 @@ use hex; -use serde::{Deserialize, Serialize}; -use serde_json::{Error as JSONError, Value}; use std::fmt; use bitcoin::Txid; -#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone, Hash)] +#[derive(Debug, Eq, PartialEq, Clone, Hash)] pub struct Locator([u8; 16]); impl Locator { @@ -15,19 +13,30 @@ impl Locator { Locator(raw_locator) } - pub fn to_vec(&self) -> Vec { + pub fn serialize(&self) -> Vec { self.0.to_vec() } + + pub fn deserialize(data: Vec) -> Result { + if data.len() == 16 { + let mut raw_locator = [0; 16]; + raw_locator.copy_from_slice(&data); + Ok(Self(raw_locator)) + } else { + // TODO: Maybe add a more expressive error? + Err(()) + } + } } impl std::fmt::Display for Locator { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", hex::encode(self.to_vec())) + write!(f, "{}", hex::encode(self.serialize())) } } /// Contains data regarding an appointment between a client and the Watchtower. An appointment is requested for every new channel update. -#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] +#[derive(Debug, Eq, PartialEq, Clone)] pub struct Appointment { pub locator: Locator, pub encrypted_blob: Vec, @@ -50,14 +59,6 @@ impl Appointment { } } - pub fn from_json(data: &str) -> Result { - serde_json::from_str::(data) - } - - pub fn to_json(self) -> Value { - serde_json::to_value(&self).unwrap() - } - /// Serializes an appointment to be signed. /// The serialization follows the same ordering as the fields in the appointment: /// @@ -65,44 +66,9 @@ impl Appointment { /// /// All values are big endian. pub fn serialize(&self) -> Vec { - let mut result = self.locator.to_vec(); + let mut result = self.locator.serialize(); result.extend(&self.encrypted_blob); result.extend(self.to_self_delay.to_be_bytes().to_vec()); result } } - -#[cfg(test)] -mod tests { - use super::*; - use serde_json::json; - - #[test] - fn test_from_json() { - let locator = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; - let encrypted_blob = [1, 2, 3, 4].to_vec(); - let to_self_delay = 21; - let appointment = Appointment::new(locator, encrypted_blob.clone(), to_self_delay); - - let data = json!(appointment).to_string(); - let a = Appointment::from_json(&data).unwrap(); - - assert_eq!(a.locator, Locator(locator)); - assert_eq!(a.encrypted_blob, encrypted_blob); - assert_eq!(a.to_self_delay, to_self_delay); - } - - #[test] - fn test_to_json() { - let locator = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; - let encrypted_blob = [1, 2, 3, 4].to_vec(); - let to_self_delay = 21; - let appointment = Appointment::new(locator, encrypted_blob.clone(), to_self_delay); - - let a_json = appointment.to_json(); - - assert_eq!(a_json["locator"], json!(locator)); - assert_eq!(a_json["encrypted_blob"], json!(encrypted_blob)); - assert_eq!(a_json["to_self_delay"], json!(to_self_delay)); - } -} diff --git a/teos-common/src/lib.rs b/teos-common/src/lib.rs index e3f52b6..ce1b759 100644 --- a/teos-common/src/lib.rs +++ b/teos-common/src/lib.rs @@ -3,65 +3,17 @@ pub mod constants; pub mod cryptography; pub mod receipts; -use serde::de::{self, SeqAccess, Unexpected, Visitor}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use std::fmt; - -use bitcoin::secp256k1::PublicKey; +use bitcoin::secp256k1::{Error, PublicKey}; #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub struct UserId(pub PublicKey); -struct UserIdVisitor; +impl UserId { + pub fn serialize(&self) -> Vec { + self.0.serialize().to_vec() + } -impl Serialize for UserId { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_bytes(&self.0.serialize()) - } -} - -impl<'de> Visitor<'de> for UserIdVisitor { - type Value = UserId; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a 33-byte long array or sequence") - } - - fn visit_bytes(self, v: &[u8]) -> Result - where - E: de::Error, - { - match PublicKey::from_slice(v) { - Ok(pk) => Ok(UserId(pk)), - Err(_) => Err(de::Error::invalid_value(Unexpected::Bytes(v), &self)), - } - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: SeqAccess<'de>, - { - let mut vec = Vec::new(); - - while let Some(elem) = seq.next_element()? { - vec.push(elem); - } - - match PublicKey::from_slice(&vec) { - Ok(pk) => Ok(UserId(pk)), - Err(_) => Err(de::Error::invalid_value(Unexpected::Seq, &self)), - } - } -} - -impl<'de> Deserialize<'de> for UserId { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_bytes(UserIdVisitor) + pub fn deserialize(data: &[u8]) -> Result { + Ok(UserId(PublicKey::from_slice(data)?)) } } diff --git a/teos/Cargo.toml b/teos/Cargo.toml index 13d58a3..f406f6c 100644 --- a/teos/Cargo.toml +++ b/teos/Cargo.toml @@ -13,7 +13,6 @@ base64 = "0.13.0" futures = "0.3" log = "0.4" simple_logger = "1.12.1" -serde = "1.0.126" serde_json = "1.0" tokio = { version = "1.5", features = [ "io-util", "macros", "rt", "rt-multi-thread", "sync", "net", "time" ] } diff --git a/teos/src/extended_appointment.rs b/teos/src/extended_appointment.rs index 461238a..7c58b67 100644 --- a/teos/src/extended_appointment.rs +++ b/teos/src/extended_appointment.rs @@ -1,5 +1,3 @@ -use serde::{Deserialize, Serialize}; -use serde_json::{Error as JSONError, Value}; use std::fmt; use bitcoin::hashes::{ripemd160, Hash}; @@ -7,15 +5,19 @@ use bitcoin::hashes::{ripemd160, Hash}; use teos_common::appointment::{Appointment, Locator}; use teos_common::UserId; -#[derive(Debug, Clone, Copy, Serialize, Deserialize, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub struct UUID(pub [u8; 20]); impl UUID { pub fn new(locator: &Locator, user_id: &UserId) -> Self { - let mut uuid_data = locator.to_vec(); + let mut uuid_data = locator.serialize(); uuid_data.extend(&user_id.0.serialize()); UUID(ripemd160::Hash::hash(&uuid_data).into_inner()) } + + pub fn serialize(&self) -> Vec { + self.0.to_vec() + } } impl std::fmt::Display for UUID { @@ -24,7 +26,7 @@ impl std::fmt::Display for UUID { } } -#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] +#[derive(Debug, Eq, PartialEq, Clone)] pub struct ExtendedAppointment { pub inner: Appointment, pub user_id: UserId, @@ -32,7 +34,6 @@ pub struct ExtendedAppointment { pub start_block: u32, } -#[derive(Serialize, Deserialize)] pub struct AppointmentSummary { locator: Locator, user_id: UserId, @@ -59,14 +60,10 @@ impl ExtendedAppointment { user_id: self.user_id, } } +} - pub fn from_json(data: &str) -> Result { - serde_json::from_str::(data) - } - - pub fn to_json(self) -> Value { - serde_json::to_value(&self).unwrap() - } +pub fn compute_appointment_slots(blob_size: usize, blob_max_size: usize) -> u32 { + (blob_size as f32 / blob_max_size as f32).ceil() as u32 } #[cfg(test)] @@ -74,7 +71,6 @@ mod tests { use super::*; use bitcoin::secp256k1::key::ONE_KEY; use bitcoin::secp256k1::{PublicKey, Secp256k1}; - use serde_json::json; use teos_common::appointment::Appointment; use teos_common::UserId; @@ -92,56 +88,4 @@ mod tests { assert_eq!(e.inner.locator, s.locator); assert_eq!(e.user_id, s.user_id); } - - #[test] - fn test_from_json() { - let locator = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; - let encrypted_blob = [1, 2, 3, 4].to_vec(); - let to_self_delay = 21; - let appointment = Appointment::new(locator, encrypted_blob, to_self_delay); - - let user_id = UserId(PublicKey::from_secret_key(&Secp256k1::new(), &ONE_KEY)); - let user_signature = String::new(); - let start_block = 42; - - let data = json!({ - "inner": appointment, - "user_id": user_id, - "user_signature": user_signature, - "start_block": start_block, - }) - .to_string(); - - let e = ExtendedAppointment::from_json(&data).unwrap(); - - assert_eq!(e.inner, appointment); - assert_eq!(e.user_id, user_id); - assert_eq!(e.user_signature, user_signature); - assert_eq!(e.start_block, start_block); - } - - #[test] - fn test_to_json() { - let locator = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; - let encrypted_blob = [1, 2, 3, 4].to_vec(); - let to_self_delay = 21; - let appointment = Appointment::new(locator, encrypted_blob, to_self_delay); - - let user_id = UserId(PublicKey::from_secret_key(&Secp256k1::new(), &ONE_KEY)); - let user_signature = String::new(); - let start_block = 42; - - let extended_appointment = ExtendedAppointment::new( - appointment.clone(), - user_id, - user_signature.clone(), - start_block, - ); - let e_json = extended_appointment.to_json(); - - assert_eq!(e_json["inner"], json!(appointment)); - assert_eq!(e_json["user_id"], json!(user_id)); - assert_eq!(e_json["user_signature"], json!(user_signature)); - assert_eq!(e_json["start_block"], json!(start_block)); - } } diff --git a/teos/src/gatekeeper.rs b/teos/src/gatekeeper.rs index 2373027..1bd8354 100644 --- a/teos/src/gatekeeper.rs +++ b/teos/src/gatekeeper.rs @@ -1,5 +1,3 @@ -use serde::{Deserialize, Serialize}; -use serde_json::{Error as JSONError, Value}; use std::cell::RefCell; use std::collections::{HashMap, HashSet}; @@ -11,9 +9,9 @@ use teos_common::cryptography; use teos_common::receipts::RegistrationReceipt; use teos_common::UserId; -use crate::extended_appointment::{ExtendedAppointment, UUID}; +use crate::extended_appointment::{compute_appointment_slots, ExtendedAppointment, UUID}; -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct UserInfo { pub(crate) available_slots: u32, pub(crate) subscription_expiry: u32, @@ -28,13 +26,6 @@ impl UserInfo { appointments: HashMap::new(), } } - pub fn from_json(data: &str) -> Result { - serde_json::from_str::(data) - } - - pub fn to_json(self) -> Value { - serde_json::to_value(&self).unwrap() - } } #[derive(Debug, PartialEq)] @@ -143,9 +134,10 @@ impl Gatekeeper { let user_info = borrowed.get_mut(user_id).unwrap(); let used_slots = user_info.appointments.get(&uuid).map_or(0, |x| x.clone()); - let required_slots = (appointment.inner.encrypted_blob.len() as f32 - / ENCRYPTED_BLOB_MAX_SIZE as f32) - .ceil() as u32; + let required_slots = compute_appointment_slots( + appointment.inner.encrypted_blob.len(), + ENCRYPTED_BLOB_MAX_SIZE, + ); let diff = required_slots as i64 - used_slots as i64; if diff <= user_info.available_slots as i64 {