Skip to content

Commit

Permalink
getregistrationreceipt working in Non-Accountable mode
Browse files Browse the repository at this point in the history
  • Loading branch information
1010adigupta committed Jun 21, 2023
1 parent 1a89c5d commit 6d1c3a0
Show file tree
Hide file tree
Showing 17 changed files with 244 additions and 31 deletions.
5 changes: 4 additions & 1 deletion teos-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ bitcoin = { version = "0.28.0", features = [ "use-serde" ] }
lightning = "0.0.108"

[build-dependencies]
tonic-build = "0.6"
tonic-build = "0.6"

[features]
notAccountable = []
2 changes: 1 addition & 1 deletion teos-common/proto/common/teos/v2/user.proto
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ message RegisterRequest {
uint32 available_slots = 2;
uint32 subscription_start = 3;
uint32 subscription_expiry = 4;
string subscription_signature = 5;
optional string subscription_signature = 5;
}

message GetSubscriptionInfoRequest {
Expand Down
7 changes: 6 additions & 1 deletion teos-common/src/receipts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,19 @@ impl RegistrationReceipt {
// TODO: Check if there's any case where this can actually fail. Don't unwrap if so.
self.signature = Some(cryptography::sign(&self.to_vec(), sk).unwrap());
}

#[cfg(not(feature = "notAccountable"))]
pub fn verify(&self, id: &UserId) -> bool {
if let Some(signature) = self.signature() {
cryptography::verify(&self.to_vec(), &signature, &id.0)
} else {
false
}
}
#[cfg(feature = "notAccountable")]
pub fn verify(&self, id: &UserId) -> bool {
true
}

}

/// Proof that a certain state was backed up with the tower.
Expand Down
4 changes: 4 additions & 0 deletions teos/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ jsonrpc-http-server = "17.1.0"
rand = "0.8.4"
tempdir = "0.3.7"
tokio-stream = { version = "0.1.5", features = [ "net" ] }

[features]
notAccountable = []

5 changes: 5 additions & 0 deletions teos/data_dir/ca-key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgtN56b2TvxnxpxbGr
MYsxYa0XL3Z9hHqAMALlLMsjVLGhRANCAASosRDTebN0QMAwYf95myHKY6EF/t4M
cGQ6SSa/ZEgxTmy5k/GQYuXzy+ly7wJKf206yO8GzRx/1WlpX3FT3jaD
-----END PRIVATE KEY-----
10 changes: 10 additions & 0 deletions teos/data_dir/ca.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBdDCCARqgAwIBAgIJALLz0HV76fWzMAoGCCqGSM49BAMCMBcxFTATBgNVBAMM
DHRlb3MgUm9vdCBDQTAgFw03NTAxMDEwMDAwMDBaGA80MDk2MDEwMTAwMDAwMFow
FzEVMBMGA1UEAwwMdGVvcyBSb290IENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAEqLEQ03mzdEDAMGH/eZshymOhBf7eDHBkOkkmv2RIMU5suZPxkGLl88vpcu8C
Sn9tOsjvBs0cf9VpaV9xU942g6NNMEswGQYDVR0RBBIwEIIDY2xugglsb2NhbGhv
c3QwHQYDVR0OBBYEFLP16Xt10POyIGAdVbTbEqiEKiXmMA8GA1UdEwEB/wQFMAMB
Af8wCgYIKoZIzj0EAwIDSAAwRQIgT5ZKkWywur6OiyUkjAzgcg0SipU9HDKnAYis
GZfqLjUCIQCy2FqPqsO4rFb7JkP2fpSu4l3fQJY8g+ZeEyK2VucLEg==
-----END CERTIFICATE-----
5 changes: 5 additions & 0 deletions teos/data_dir/client-key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg12hR3kPQnrrhTSEM
yHkDoblFg/EC/XtbOmRo2ZKdeA2hRANCAATwfs9UQfAWUBjmgi1/oQ54gYcBnbSP
ZobEn2pDy+YU6Rh2FLway8Ytne1xQ6iowSh1EIH2XWYuWNDtSeVvv9ln
-----END PRIVATE KEY-----
9 changes: 9 additions & 0 deletions teos/data_dir/client.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN CERTIFICATE-----
MIIBRzCB7qADAgECAgkAmlmq3GzgOMYwCgYIKoZIzj0EAwIwFzEVMBMGA1UEAwwM
dGVvcyBSb290IENBMCAXDTc1MDEwMTAwMDAwMFoYDzQwOTYwMTAxMDAwMDAwWjAb
MRkwFwYDVQQDDBB0ZW9zIGdycGMgQ2xpZW50MFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAE8H7PVEHwFlAY5oItf6EOeIGHAZ20j2aGxJ9qQ8vmFOkYdhS8GsvGLZ3t
cUOoqMEodRCB9l1mLljQ7Unlb7/ZZ6MdMBswGQYDVR0RBBIwEIIDY2xugglsb2Nh
bGhvc3QwCgYIKoZIzj0EAwIDSAAwRQIhAIROzv0qei4YsFywUHtyhQv+JEDzKawP
hL5kZu2uzlwvAiBZU1TG3LLgm/YumqzFSEt6cs5qM4r93Y7vHaVZQZ0I8w==
-----END CERTIFICATE-----
Binary file added teos/data_dir/regtest/teos_db.sql3
Binary file not shown.
5 changes: 5 additions & 0 deletions teos/data_dir/server-key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgQkEWrVRyGsV3qJN+
qMQIjva5uRJSkHFfWj/jN5NE5aahRANCAARBSZchT2XlHvWAucSDQ4rziyBfT86k
88asPnrqBPn1tgDa8FG1gGzuKShwm5cbmq8D7BqSYvIW9FO4TI6yb5iX
-----END PRIVATE KEY-----
9 changes: 9 additions & 0 deletions teos/data_dir/server.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN CERTIFICATE-----
MIIBRzCB7qADAgECAgkA7vIgeKbbSRMwCgYIKoZIzj0EAwIwFzEVMBMGA1UEAwwM
dGVvcyBSb290IENBMCAXDTc1MDEwMTAwMDAwMFoYDzQwOTYwMTAxMDAwMDAwWjAb
MRkwFwYDVQQDDBB0ZW9zIGdycGMgU2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEQUmXIU9l5R71gLnEg0OK84sgX0/OpPPGrD566gT59bYA2vBRtYBs7iko
cJuXG5qvA+wakmLyFvRTuEyOsm+Yl6MdMBswGQYDVR0RBBIwEIIDY2xugglsb2Nh
bGhvc3QwCgYIKoZIzj0EAwIDSAAwRQIgNHocDiEeyM1uwCSxrFkdEeQR6GOyVw8v
mzb4eOLRTusCIQDFg4YzVZFwMz5A/8zeNT9QO3OVOEBfaVrv5CBoef11ew==
-----END CERTIFICATE-----
33 changes: 33 additions & 0 deletions teos/data_dir/teos.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# API
api_bind = "127.0.0.1"
api_port = 9814
tor_control_port = 9051
onion_hidden_service_port = 9814
tor_support = false

# RPC
rpc_bind = "127.0.0.1"
rpc_port = 8814

# bitcoind
btc_network = "regtest"
btc_rpc_user = "exch"
btc_rpc_password = "goodpass"
btc_rpc_connect = "localhost"
btc_rpc_port = 18443

# Flags
debug = false
deps_debug = false
overwrite_key = false

# General
subscription_slots = 10000
subscription_duration = 4320
expiry_delta = 6
min_to_self_delay = 20
polling_delta = 60

# Internal API
internal_api_bind = "127.0.0.1"
internal_api_port = 50051
84 changes: 58 additions & 26 deletions teos/src/api/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,34 +67,66 @@ impl InternalAPI {
#[tonic::async_trait]
impl PublicTowerServices for Arc<InternalAPI> {
/// Register endpoint. Part of the public API. Internally calls [Watcher::register].
async fn register(
&self,
request: Request<common_msgs::RegisterRequest>,
) -> Result<Response<common_msgs::RegisterResponse>, Status> {
self.check_service_unavailable()?;
let req_data = request.into_inner();

let user_id = UserId::from_slice(&req_data.user_id).map_err(|_| {
Status::new(
Code::InvalidArgument,
"Provided public key does not match expected format (33-byte compressed key)",
)
})?;
#[cfg(not(feature = "notAccountable"))]
async fn register(
&self,
request: Request<common_msgs::RegisterRequest>,
) -> Result<Response<common_msgs::RegisterResponse>, Status> {
self.check_service_unavailable()?;
let req_data = request.into_inner();

let user_id = UserId::from_slice(&req_data.user_id).map_err(|_| {
Status::new(
Code::InvalidArgument,
"Provided public key does not match expected format (33-byte compressed key)",
)
})?;

match self.watcher.register(user_id) {
Ok(receipt) => Ok(Response::new(common_msgs::RegisterResponse {
user_id: req_data.user_id,
available_slots: receipt.available_slots(),
subscription_start: receipt.subscription_start(),
subscription_expiry: receipt.subscription_expiry(),
subscription_signature: receipt.signature().unwrap(),
})),
Err(_) => Err(Status::new(
Code::ResourceExhausted,
"Subscription maximum slots count reached",
)),
}
}

match self.watcher.register(user_id) {
Ok(receipt) => Ok(Response::new(common_msgs::RegisterResponse {
user_id: req_data.user_id,
available_slots: receipt.available_slots(),
subscription_start: receipt.subscription_start(),
subscription_expiry: receipt.subscription_expiry(),
subscription_signature: receipt.signature().unwrap(),
})),
Err(_) => Err(Status::new(
Code::ResourceExhausted,
"Subscription maximum slots count reached",
)),
}
#[cfg(feature = "notAccountable")]
async fn register(
&self,
request: Request<common_msgs::RegisterRequest>,
) -> Result<Response<common_msgs::RegisterResponse>, Status> {
self.check_service_unavailable()?;
let req_data = request.into_inner();

let user_id = UserId::from_slice(&req_data.user_id).map_err(|_| {
Status::new(
Code::InvalidArgument,
"Provided public key does not match expected format (33-byte compressed key)",
)
})?;

match self.watcher.register(user_id) {
Ok(receipt) => Ok(Response::new(common_msgs::RegisterResponse {
user_id: req_data.user_id,
available_slots: receipt.available_slots(),
subscription_start: receipt.subscription_start(),
subscription_expiry: receipt.subscription_expiry(),
subscription_signature: None,
})),
Err(_) => Err(Status::new(
Code::ResourceExhausted,
"Subscription maximum slots count reached",
)),
}
}


/// Add appointment endpoint. Part of the public API. Internally calls [Watcher::add_appointment].
async fn add_appointment(
Expand Down
10 changes: 9 additions & 1 deletion teos/src/watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,20 @@ impl Watcher {

/// Registers a new user within the [Watcher]. This request is passed to the [Gatekeeper], who is in
/// charge of managing users.
#[cfg(not(feature = "notAccountable"))]
pub(crate) fn register(&self, user_id: UserId) -> Result<RegistrationReceipt, MaxSlotsReached> {
let mut receipt = self.gatekeeper.add_update_user(user_id)?;
receipt.sign(&self.signing_key);


Ok(receipt)
}

#[cfg(feature = "notAccountable")]
pub(crate) fn register(&self, user_id: UserId) -> Result<RegistrationReceipt, MaxSlotsReached> {
let receipt = self.gatekeeper.add_update_user(user_id)?;
Ok(receipt)
}


/// Adds a new [Appointment] to the tower.
///
Expand Down
5 changes: 4 additions & 1 deletion watchtower-plugin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ teos-common = { path = "../teos-common" }

[dev-dependencies]
mockito = "0.32.4"
tempdir = "0.3.7"
tempdir = "0.3.7"

[features]
notAccountable = []
52 changes: 52 additions & 0 deletions watchtower-plugin/src/dbm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ impl DBM {
///
/// This function MUST be guarded against inserting duplicate (tower_id, subscription_expiry) pairs.
/// This is currently done in WTClient::add_update_tower.
#[cfg(not(feature = "notAccountable"))]
pub fn store_tower_record(
&mut self,
tower_id: TowerId,
Expand All @@ -165,7 +166,28 @@ impl DBM {

tx.commit().map_err(Error::Unknown)
}
#[cfg(feature = "notAccountable")]
pub fn store_tower_record(
&mut self,
tower_id: TowerId,
net_addr: &str,
receipt: &RegistrationReceipt,
) -> Result<(), Error> {
let tx = self.get_mut_connection().transaction().unwrap();
tx.execute(
"INSERT INTO towers (tower_id, net_addr, available_slots)
VALUES (?1, ?2, ?3)
ON CONFLICT (tower_id) DO UPDATE SET net_addr = ?2, available_slots = ?3",
params![tower_id.to_vec(), net_addr, receipt.available_slots()],
)
.map_err(Error::Unknown)?;
tx.execute(
"INSERT INTO registration_receipts (tower_id, available_slots, subscription_start, subscription_expiry)
VALUES (?1, ?2, ?3, ?4)",
params![tower_id.to_vec(), receipt.available_slots(), receipt.subscription_start(), receipt.subscription_expiry()]).map_err( Error::Unknown)?;

tx.commit().map_err(Error::Unknown)
}
/// Loads a tower record from the database.
///
/// Tower records are composed from the tower information and the appointment data. The latter is split in:
Expand Down Expand Up @@ -212,6 +234,7 @@ impl DBM {
/// Loads the latest registration receipt for a given tower.
///
/// Latests is determined by the one with the `subscription_expiry` further into the future.
#[cfg(not(feature = "notAccountable"))]
pub fn load_registration_receipt(
&self,
tower_id: TowerId,
Expand Down Expand Up @@ -241,6 +264,35 @@ impl DBM {
.ok()
}

#[cfg(feature = "notAccountable")]

pub fn load_registration_receipt(
&self,
tower_id: TowerId,
user_id: UserId,
) -> Option<RegistrationReceipt> {
let mut stmt = self
.connection
.prepare(
"SELECT available_slots, subscription_start, subscription_expiry
FROM registration_receipts
WHERE tower_id = ?1 AND subscription_expiry = (SELECT MAX(subscription_expiry)
FROM registration_receipts
WHERE tower_id = ?1)",
)
.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();

Ok(RegistrationReceipt::new(
user_id, slots, start, expiry,
))
})
.ok()
}
/// Removes a tower record from the database.
///
/// This triggers a cascade deletion of all related data, such as appointments, appointment receipts, etc. As long as there is a single
Expand Down
30 changes: 30 additions & 0 deletions watchtower-plugin/src/net/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ impl From<RequestError> for AddAppointmentError {
}

/// Handles the logic of interacting with the `register` endpoint of the tower.
#[cfg(not(feature = "notAccountable"))]
pub async fn register(
tower_id: TowerId,
user_id: UserId,
Expand Down Expand Up @@ -85,6 +86,35 @@ pub async fn register(
)
})
}
#[cfg(feature = "notAccountable")]
pub async fn register(
tower_id: TowerId,
user_id: UserId,
tower_net_addr: &NetAddr,
proxy: &Option<ProxyInfo>,
) -> Result<RegistrationReceipt, RequestError> {
log::info!("Registering in the Eye of Satoshi (tower_id={tower_id})");
process_post_response(
post_request(
tower_net_addr,
Endpoint::Register,
&common_msgs::RegisterRequest {
user_id: user_id.to_vec(),
},
proxy,
)
.await,
)
.await
.map(|r: common_msgs::RegisterResponse| {
RegistrationReceipt::new(
user_id,
r.available_slots,
r.subscription_start,
r.subscription_expiry
)
})
}

/// Encapsulates the logging and response parsing of sending and appointment to the tower.
pub async fn add_appointment(
Expand Down

0 comments on commit 6d1c3a0

Please sign in to comment.