Skip to content

Commit c14543d

Browse files
committed
Add start_time to registration receipt
1 parent 3175aca commit c14543d

File tree

14 files changed

+597
-148
lines changed

14 files changed

+597
-148
lines changed

teos-common/proto/common/teos/v2/user.proto

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ message RegisterRequest {
1212

1313
bytes user_id = 1;
1414
uint32 available_slots = 2;
15-
uint32 subscription_expiry = 3;
16-
string subscription_signature = 4;
15+
uint32 subscription_start = 3;
16+
uint32 subscription_expiry = 4;
17+
string subscription_signature = 5;
1718
}
1819

1920
message GetSubscriptionInfoRequest {

teos-common/src/receipts.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,40 @@ use bitcoin::secp256k1::SecretKey;
66

77
use crate::{cryptography, UserId};
88

9-
#[derive(Serialize, Debug)]
9+
/// Proof that a user has registered with a tower. This serves two purposes:
10+
///
11+
/// - First, the user is able to prove that the tower agreed on providing a service. If a tower refuses to accept appointments
12+
/// from a user (claiming the subscription has expired) but the expiry time has still not passed and the tower cannot
13+
/// provide the relevant appointments signed by the user, it means it is cheating.
14+
/// - Second, it serves as proof, alongside an appointment receipt, that an appointment was not fulfilled. A registration receipt
15+
/// specifies a subscription period (`subscription_start` - `subscription_expiry`) and the appointment a `start_block` so inclusion
16+
/// can be proved.
17+
///
18+
/// TODO: / DISCUSS: In order to minimize the amount of receipts the user has to store, the tower could batch subscription receipts
19+
/// as long as the user info is still known. That is, if a user has a subscription with range (S, E) and the user renews the subscription
20+
/// before the tower wipes their data, then the tower can create a new receipt with (S, E') for E' > E instead of a second receipt (E, E').
21+
// Notice this only applies as long as there is no gap between the two subscriptions.
22+
#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
1023
pub struct RegistrationReceipt {
1124
user_id: UserId,
1225
available_slots: u32,
26+
subscription_start: u32,
1327
subscription_expiry: u32,
1428
#[serde(skip)]
1529
signature: Option<String>,
1630
}
1731

1832
impl RegistrationReceipt {
19-
pub fn new(user_id: UserId, available_slots: u32, subscription_expiry: u32) -> Self {
33+
pub fn new(
34+
user_id: UserId,
35+
available_slots: u32,
36+
subscription_start: u32,
37+
subscription_expiry: u32,
38+
) -> Self {
2039
RegistrationReceipt {
2140
user_id,
2241
available_slots,
42+
subscription_start,
2343
subscription_expiry,
2444
signature: None,
2545
}
@@ -28,12 +48,14 @@ impl RegistrationReceipt {
2848
pub fn with_signature(
2949
user_id: UserId,
3050
available_slots: u32,
51+
subscription_start: u32,
3152
subscription_expiry: u32,
3253
signature: String,
3354
) -> Self {
3455
RegistrationReceipt {
3556
user_id,
3657
available_slots,
58+
subscription_start,
3759
subscription_expiry,
3860
signature: Some(signature),
3961
}
@@ -47,6 +69,10 @@ impl RegistrationReceipt {
4769
self.available_slots
4870
}
4971

72+
pub fn subscription_start(&self) -> u32 {
73+
self.subscription_start
74+
}
75+
5076
pub fn subscription_expiry(&self) -> u32 {
5177
self.subscription_expiry
5278
}
@@ -59,6 +85,7 @@ impl RegistrationReceipt {
5985
let mut ser = Vec::new();
6086
ser.extend_from_slice(&self.user_id.to_vec());
6187
ser.extend_from_slice(&self.available_slots.to_be_bytes());
88+
ser.extend_from_slice(&self.subscription_start.to_be_bytes());
6289
ser.extend_from_slice(&self.subscription_expiry.to_be_bytes());
6390

6491
ser
@@ -78,6 +105,9 @@ impl RegistrationReceipt {
78105
}
79106
}
80107

108+
/// Proof that a certain state was backed up with the tower.
109+
///
110+
/// Appointment receipts can be used alongside a registration receipt that covers it, and on chain data (a breach not being reacted with a penalty), to prove a tower has not reacted to a channel breach.
81111
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
82112
pub struct AppointmentReceipt {
83113
user_signature: String,

teos-common/src/test_utils.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,26 @@ pub fn generate_random_appointment(dispute_txid: Option<&Txid>) -> Appointment {
5353
}
5454

5555
pub fn get_random_registration_receipt() -> RegistrationReceipt {
56-
RegistrationReceipt::new(get_random_user_id(), get_random_int(), get_random_int())
56+
let (sk, _) = cryptography::get_random_keypair();
57+
let start = get_random_int();
58+
let mut receipt =
59+
RegistrationReceipt::new(get_random_user_id(), get_random_int(), start, start + 420);
60+
receipt.sign(&sk);
61+
62+
receipt
63+
}
64+
65+
pub fn get_registration_receipt_from_previous(r: &RegistrationReceipt) -> RegistrationReceipt {
66+
let (sk, _) = cryptography::get_random_keypair();
67+
let mut receipt = RegistrationReceipt::new(
68+
r.user_id(),
69+
r.available_slots() + 1 + get_random_int::<u8>() as u32,
70+
r.subscription_start(),
71+
r.subscription_expiry() + 1 + get_random_int::<u8>() as u32,
72+
);
73+
receipt.sign(&sk);
74+
75+
receipt
5776
}
5877

5978
pub fn get_random_appointment_receipt(tower_sk: SecretKey) -> AppointmentReceipt {

teos/src/api/internal.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ impl PublicTowerServices for Arc<InternalAPI> {
7777
Ok(receipt) => Ok(Response::new(common_msgs::RegisterResponse {
7878
user_id: req_data.user_id,
7979
available_slots: receipt.available_slots(),
80+
subscription_start: receipt.subscription_start(),
8081
subscription_expiry: receipt.subscription_expiry(),
8182
subscription_signature: receipt.signature().unwrap(),
8283
})),

0 commit comments

Comments
 (0)