Fixup and add comments, README to Lox Library
This commit is contained in:
parent
73b04b9a19
commit
e356034dae
|
@ -9,10 +9,10 @@
|
||||||
},
|
},
|
||||||
"rtype": {
|
"rtype": {
|
||||||
"endpoint": "http://127.0.0.1:7100/resources",
|
"endpoint": "http://127.0.0.1:7100/resources",
|
||||||
"name": "https",
|
"name": "lox",
|
||||||
"token": "HttpsApiTokenPlaceholder",
|
"token": "LoxApiTokenPlaceholder",
|
||||||
"types": [
|
"types": [
|
||||||
"obfs2",
|
"obfs4",
|
||||||
"scramblesuit"
|
"scramblesuit"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,40 @@
|
||||||
# Lox
|
# Lox
|
||||||
|
|
||||||
Lox is a reputation-based bridge distribution system that provides privacy protection to users and their social graph and is open to all users.
|
Lox is a reputation-based bridge distribution system that provides privacy protection to users and their social graph and is open to all users.
|
||||||
Lox is written in rust and requires `cargo` to test. [Install Rust](https://www.rust-lang.org/tools/install). We used Rust version 1.56.0.
|
|
||||||
|
|
||||||
Note that this implementation is coded such that the reachability certificate expires at 00:00 UTC. In reality, if the bucket is still reachable, a user could simply request a new reachability token if their request fails for this reason (a new certificate should be available prior to the outdated certificate expiring).
|
The protocols in the Lox-library are consistent with the Lox system described
|
||||||
|
in [Tulloch and Goldberg](https://petsymposium.org/popets/2023/popets-2023-0029.php) (and in greater detail [here](https://uwspace.uwaterloo.ca/handle/10012/18333)). However, this implementation may diverge from the theory over time as the system is deployed and its limitations are better illuminated. The [original version of this library](https://git-crysp.uwaterloo.ca/iang/lox) will remain a more precise implementation of the theory.
|
||||||
|
|
||||||
|
Lox is written in rust and requires `cargo` to test. [Install Rust](https://www.rust-lang.org/tools/install). We used Rust version 1.65.0.
|
||||||
|
|
||||||
|
## Notable Changes from the original repository
|
||||||
|
|
||||||
|
Some changes have been made to integrate the existing Lox protocols with Tor's
|
||||||
|
bridge distributor [rdsys](https://gitlab.torproject.org/tpo/anti-censorship/rdsys),
|
||||||
|
but so far, these have not affected the Lox protocols themselves.
|
||||||
|
|
||||||
|
These changes are necessary to keep the consistentcy of bridges in buckets that Lox requires while working with the reality of how rdsys/Tor currently receives and distributes information about bridges. The changes to Lox are:
|
||||||
|
1. Add a `uid_fingerprint` field to the BridgeLine which helps with bridge lookup and
|
||||||
|
corresponds (roughly) to the unique fingerprint rdsys gives to each bridge
|
||||||
|
(made up of a hash of the IP and pluggable transport type)
|
||||||
|
2. Allow for the details of a bridge to be updated. This has been added to
|
||||||
|
[`crates/lox-library/src/lib.rs`](https://gitlab.torproject.org/tpo/anti-censorship/lox-rs/-/blob/main/crates/lox-library/src/lib.rs) and accounts for the fact that some details
|
||||||
|
of an existing bridge (i.e., that has a matching fingerprint) may be updated
|
||||||
|
from time to time.
|
||||||
|
3. Allow for a bridge to be replaced without penalty. This has also been added to
|
||||||
|
[`crates/lox-library/src/lib.rs`](https://gitlab.torproject.org/tpo/anti-censorship/lox-rs/-/blob/main/crates/lox-library/src/lib.rs)
|
||||||
|
and accounts for the fact that Tor currently does not have a robust way of
|
||||||
|
[knowing that a bridge is blocked](https://gitlab.torproject.org/tpo/anti-censorship/censorship-analysis/-/issues/40035), but does have some tests (namely,
|
||||||
|
[bridgestrap](https://gitlab.torproject.org/tpo/anti-censorship/bridgestrap) and [onbasca](https://gitlab.torproject.org/tpo/network-health/onbasca)) that help to determine if a
|
||||||
|
bridge should not be distributed. Since we do not know if the results of
|
||||||
|
these tests indicate a blocking event, we are allowing for bridges that
|
||||||
|
rdsys marks as unsuitable for distribution to be updated without penalty in the Lox library.
|
||||||
|
4. The vectors within `bridge_table.rs` have been refactored into HashMaps that use a unique `u32` for lookup. This has led to a
|
||||||
|
number of changes around how bridges are inserted/removed from the bridge table but does not impact the overall functionality of the Lox system.
|
||||||
|
5. The `DupFilter` has been changed from a `HashMap` to a `HashSet`, primarily because this is easier to Serialize/Deserialize when storing the state of the Lox system to recover from failure or to be able to roll back to a previous state.
|
||||||
|
6. The [`dalek-cryptography`](https://dalek.rs/) libraries have been updated to their most recent versions and the `zkp` library has been forked (until/unless this is fixed in one of the existing upstream repos) to fix a bug that appears when a public attribute is set to 0 (previously impacting only the blockage migration protocol when a user's invitations are set to 0 after migrating). The fork of `zkp` also includes similar updates to `dalek-cryptography` dependencies and some others such as `rand`.
|
||||||
|
7. Many tests that were used to create the Lox paper/thesis and measure the performance of the system were removed from this repository as they are unnecessary in a deployment scenario. They are still available in the [original repository](https://git-crysp.uwaterloo.ca/iang/lox).
|
||||||
|
|
||||||
|
### Other important Notes
|
||||||
|
|
||||||
|
As with the original implementation, this implementation is coded such that the reachability certificate expires at 00:00 UTC. Therefore, if an unlucky user requests a reachability certificate just before the 00:00 UTC and tries to use it just after, the request will fail. If the bucket is still reachable, a user can simply request a new reachability token if their request fails for this reason (a new certificate should be available prior to the outdated certificate expiring).
|
||||||
|
|
|
@ -246,35 +246,40 @@ struct K {
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct BridgeTable {
|
pub struct BridgeTable {
|
||||||
// All structures in the bridgetable are indexed by counter
|
/// All structures in the bridgetable are indexed by counter
|
||||||
pub counter: u32,
|
pub counter: u32,
|
||||||
|
/// The keys of all buckets, indexed by counter, that are still part of the bridge table.
|
||||||
pub keys: HashMap<u32, [u8; 16]>,
|
pub keys: HashMap<u32, [u8; 16]>,
|
||||||
|
/// All buckets, indexed by counter corresponding to the key above, that are
|
||||||
|
/// part of the bridge table.
|
||||||
pub buckets: HashMap<u32, [BridgeLine; MAX_BRIDGES_PER_BUCKET]>,
|
pub buckets: HashMap<u32, [BridgeLine; MAX_BRIDGES_PER_BUCKET]>,
|
||||||
pub encbuckets: HashMap<u32, EncryptedBucket>,
|
pub encbuckets: HashMap<u32, EncryptedBucket>,
|
||||||
/// Individual bridges that are reachable
|
/// Individual bridges that are reachable.
|
||||||
#[serde_as(as = "HashMap<serde_with::json::JsonString, _>")]
|
#[serde_as(as = "HashMap<serde_with::json::JsonString, _>")]
|
||||||
pub reachable: HashMap<BridgeLine, Vec<(u32, usize)>>,
|
pub reachable: HashMap<BridgeLine, Vec<(u32, usize)>>,
|
||||||
/// bucket ids of "hot spare" buckets. These buckets are not handed
|
/// Bucket ids of "hot spare" buckets. These buckets are not handed
|
||||||
/// to users, nor do they have any Migration credentials pointing to
|
/// to users, nor do they have any Migration credentials pointing to
|
||||||
/// them. When a new Migration credential is needed, a bucket is
|
/// them. When a new Migration credential is needed, a bucket is
|
||||||
/// removed from this set and used for that purpose.
|
/// removed from this set and used for that purpose.
|
||||||
pub spares: HashSet<u32>,
|
pub spares: HashSet<u32>,
|
||||||
/// In some instances a single bridge may need to be added to a bucket
|
/// In some instances a single bridge may need to be added to a bucket as a replacement
|
||||||
/// In that case, a spare bucket will be removed from the set of spare bridges. One
|
/// or otherwise. In that case, a spare bucket will be removed from the set of spares, one
|
||||||
|
/// bridge will be used as the replacement and the left over bridges will be appended to
|
||||||
|
/// unallocated_bridges.
|
||||||
pub unallocated_bridges: Vec<BridgeLine>,
|
pub unallocated_bridges: Vec<BridgeLine>,
|
||||||
// To prevent issues with a counter for the hashmap keys, we keep a list of keys that
|
// To prevent issues with the counter for the hashmap keys, keep a list of keys that
|
||||||
// no longer match any buckets that can be used before increasing the counter
|
// no longer match any buckets that can be used before increasing the counter.
|
||||||
pub recycleable_keys: Vec<u32>,
|
pub recycleable_keys: Vec<u32>,
|
||||||
// We maintain a list of keys that have been blocked (bucket_id: u32), as well as the
|
// A list of keys that have been blocked (bucket_id: u32), as well as the
|
||||||
// time (julian_date: u32) of their blocking so that they can be repurposed with new
|
// time (julian_date: u32) of their blocking so that they can be repurposed with new
|
||||||
// buckets after the EXPIRY_DATE
|
// buckets after the EXPIRY_DATE.
|
||||||
pub blocked_keys: Vec<(u32, u32)>,
|
pub blocked_keys: Vec<(u32, u32)>,
|
||||||
// Similarly, we maintain a list of open entry buckets (bucket_id: u32) and the time they were
|
// Similarly, a list of open entry buckets (bucket_id: u32) and the time they were
|
||||||
// created (julian_date: u32) so they will be listed as expired after the EXPIRY_DATE
|
// created (julian_date: u32) so they will be listed as expired after the EXPIRY_DATE.
|
||||||
// TODO: add open entry buckets to the open_inv_keys only once they have been distributed
|
// TODO: add open entry buckets to the open_inv_keys only once they have been distributed
|
||||||
pub open_inv_keys: Vec<(u32, u32)>,
|
pub open_inv_keys: Vec<(u32, u32)>,
|
||||||
/// The date the buckets were last encrypted to make the encbucket.
|
/// The date the buckets were last encrypted to make the encbucket.
|
||||||
/// The encbucket must be rebuilt each day so that the Bucket
|
/// The encbucket must be rebuilt at least each day so that the Bucket
|
||||||
/// Reachability credentials in the buckets can be refreshed.
|
/// Reachability credentials in the buckets can be refreshed.
|
||||||
pub date_last_enc: u32,
|
pub date_last_enc: u32,
|
||||||
}
|
}
|
||||||
|
@ -288,7 +293,7 @@ impl BridgeTable {
|
||||||
self.buckets.len()
|
self.buckets.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Append a new bucket to the bridge table, returning its index
|
/// Insert a new bucket into the bridge table, returning its index
|
||||||
pub fn new_bucket(&mut self, index: u32, bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET]) {
|
pub fn new_bucket(&mut self, index: u32, bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET]) {
|
||||||
// Pick a random key to encrypt this bucket
|
// Pick a random key to encrypt this bucket
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
In each case, (P,Q) forms the MAC on the credential. This MAC is
|
In each case, (P,Q) forms the MAC on the credential. This MAC is
|
||||||
verifiable only by the issuing party, or if the issuing party issues a
|
verifiable only by the issuing party, or if the issuing party issues a
|
||||||
zero-knowledge proof of its correctness (as it does at issuing time). */
|
zero-knowledge proof of its correctness (as it does at issuing time).*/
|
||||||
|
|
||||||
use curve25519_dalek::ristretto::RistrettoPoint;
|
use curve25519_dalek::ristretto::RistrettoPoint;
|
||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
|
|
@ -62,10 +62,12 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPIRY_DATE is set to EXPIRY_DATE days for open-entry and blocked buckets in order to match
|
// EXPIRY_DATE is set to EXPIRY_DATE days for open-entry and blocked buckets in order to match
|
||||||
// the expiry date for Lox credentials. This particular value (EXPIRY_DATE) is chosen because
|
// the expiry date for Lox credentials.This particular value (EXPIRY_DATE) is chosen because
|
||||||
// values that are 2^k − 1 make range proofs more efficient, but this can be changed to any value
|
// values that are 2^k − 1 make range proofs more efficient, but this can be changed to any value
|
||||||
pub const EXPIRY_DATE: u32 = 511;
|
pub const EXPIRY_DATE: u32 = 511;
|
||||||
|
|
||||||
|
/// ReplaceSuccess sends a signal to the lox-distributor to inform
|
||||||
|
/// whether or not a bridge was successfully replaced
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
pub enum ReplaceSuccess {
|
pub enum ReplaceSuccess {
|
||||||
NotFound = 0,
|
NotFound = 0,
|
||||||
|
@ -73,18 +75,23 @@ pub enum ReplaceSuccess {
|
||||||
Replaced = 2,
|
Replaced = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This error is thrown if the number of buckets/keys in the bridge table
|
||||||
|
/// exceeds u32 MAX.It is unlikely this error will ever occur.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum NoAvailableIDError {
|
pub enum NoAvailableIDError {
|
||||||
#[error("Find key exhausted with no available index found!")]
|
#[error("Find key exhausted with no available index found!")]
|
||||||
ExhaustedIndexer,
|
ExhaustedIndexer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This error is thrown after the MAX_DAILY_BRIDGES threshold for bridges
|
||||||
|
/// distributed in a day has been reached
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum ExceededMaxBridgesError {
|
pub enum ExceededMaxBridgesError {
|
||||||
#[error("The maximum number of bridges has already been distributed today, please try again tomorrow!")]
|
#[error("The maximum number of bridges has already been distributed today, please try again tomorrow!")]
|
||||||
ExceededMaxBridges,
|
ExceededMaxBridges,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Private Key of the Issuer
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct IssuerPrivKey {
|
pub struct IssuerPrivKey {
|
||||||
x0tilde: Scalar,
|
x0tilde: Scalar,
|
||||||
|
@ -106,11 +113,13 @@ impl IssuerPrivKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct IssuerPubKey {
|
pub struct IssuerPubKey {
|
||||||
X: Vec<RistrettoPoint>,
|
X: Vec<RistrettoPoint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Public Key of the Issuer
|
||||||
impl IssuerPubKey {
|
impl IssuerPubKey {
|
||||||
/// Create an IssuerPubKey from the corresponding IssuerPrivKey
|
/// Create an IssuerPubKey from the corresponding IssuerPrivKey
|
||||||
pub fn new(privkey: &IssuerPrivKey) -> IssuerPubKey {
|
pub fn new(privkey: &IssuerPrivKey) -> IssuerPubKey {
|
||||||
|
@ -130,9 +139,9 @@ impl IssuerPubKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number of times a given invitation is ditributed
|
/// Number of times a given invitation is ditributed
|
||||||
pub const OPENINV_K: u32 = 10;
|
pub const OPENINV_K: u32 = 10;
|
||||||
// TODO: Decide on maximum daily number of invitations to be distributed
|
/// TODO: Decide on maximum daily number of invitations to be distributed
|
||||||
pub const MAX_DAILY_BRIDGES: u32 = 100;
|
pub const MAX_DAILY_BRIDGES: u32 = 100;
|
||||||
/// The BridgeDb. This will typically be a singleton object. The
|
/// The BridgeDb. This will typically be a singleton object. The
|
||||||
/// BridgeDb's role is simply to issue signed "open invitations" to
|
/// BridgeDb's role is simply to issue signed "open invitations" to
|
||||||
|
@ -188,6 +197,8 @@ impl BridgeDb {
|
||||||
self.openinv_buckets.remove(bucket);
|
self.openinv_buckets.remove(bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove open invitation and/or otherwise distributed buckets that have
|
||||||
|
/// become blocked or are expired to free up the index for a new bucket
|
||||||
pub fn remove_blocked_or_expired_buckets(&mut self, bucket: &u32) {
|
pub fn remove_blocked_or_expired_buckets(&mut self, bucket: &u32) {
|
||||||
if self.openinv_buckets.contains(bucket) {
|
if self.openinv_buckets.contains(bucket) {
|
||||||
println!("Removing a bucket that has not been distributed yet!");
|
println!("Removing a bucket that has not been distributed yet!");
|
||||||
|
@ -197,6 +208,7 @@ impl BridgeDb {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mark a bucket as distributed
|
||||||
pub fn mark_distributed(&mut self, bucket: u32) {
|
pub fn mark_distributed(&mut self, bucket: u32) {
|
||||||
self.distributed_buckets.push(bucket);
|
self.distributed_buckets.push(bucket);
|
||||||
}
|
}
|
||||||
|
@ -406,6 +418,9 @@ impl BridgeAuth {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// When syncing the Lox bridge table with rdsys, this function returns any bridges
|
||||||
|
/// that are found in the Lox bridge table that are not found in the Vector
|
||||||
|
/// of bridges received from rdsys through the Lox distributor.
|
||||||
pub fn find_and_remove_unaccounted_for_bridges(
|
pub fn find_and_remove_unaccounted_for_bridges(
|
||||||
&mut self,
|
&mut self,
|
||||||
accounted_for_bridges: Vec<u64>,
|
accounted_for_bridges: Vec<u64>,
|
||||||
|
@ -419,6 +434,7 @@ impl BridgeAuth {
|
||||||
unaccounted_for
|
unaccounted_for
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allocate single left over bridges to an open invitation bucket
|
||||||
pub fn allocate_bridges(
|
pub fn allocate_bridges(
|
||||||
&mut self,
|
&mut self,
|
||||||
distributor_bridges: &mut Vec<BridgeLine>,
|
distributor_bridges: &mut Vec<BridgeLine>,
|
||||||
|
@ -447,12 +463,10 @@ impl BridgeAuth {
|
||||||
// Update the details of a bridge in the bridge table. This assumes that the IP and Port
|
// Update the details of a bridge in the bridge table. This assumes that the IP and Port
|
||||||
// of a given bridge remains the same and thus can be updated.
|
// of a given bridge remains the same and thus can be updated.
|
||||||
// First we must retrieve the list of reachable bridges, then we must search for any matching our partial key
|
// First we must retrieve the list of reachable bridges, then we must search for any matching our partial key
|
||||||
// which will include the IP and Port. Then we can replace the original bridge with the updated bridge
|
// which will include the IP and Port. Finally we can replace the original bridge with the updated bridge.
|
||||||
// Returns true if the bridge has successfully updated
|
// Returns true if the bridge has successfully updated
|
||||||
pub fn bridge_update(&mut self, bridge: &BridgeLine) -> bool {
|
pub fn bridge_update(&mut self, bridge: &BridgeLine) -> bool {
|
||||||
let mut res: bool = false; //default False to assume that update failed
|
let mut res: bool = false; //default False to assume that update failed
|
||||||
//Needs to be updated since bridge will only match on some fields.
|
|
||||||
|
|
||||||
let reachable_bridges = self.bridge_table.reachable.clone();
|
let reachable_bridges = self.bridge_table.reachable.clone();
|
||||||
for reachable_bridge in reachable_bridges {
|
for reachable_bridge in reachable_bridges {
|
||||||
if reachable_bridge.0.uid_fingerprint == bridge.uid_fingerprint {
|
if reachable_bridge.0.uid_fingerprint == bridge.uid_fingerprint {
|
||||||
|
@ -490,6 +504,8 @@ impl BridgeAuth {
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempt to remove a bridge that is failing tests and replace it with a bridge from
|
||||||
|
/// available_bridge or from a spare bucket
|
||||||
pub fn bridge_replace(
|
pub fn bridge_replace(
|
||||||
&mut self,
|
&mut self,
|
||||||
bridge: &BridgeLine,
|
bridge: &BridgeLine,
|
||||||
|
@ -692,7 +708,7 @@ impl BridgeAuth {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since buckets are moved around in the bridge_table, finding a lookup key that
|
// Since buckets are moved around in the bridge_table, finding a lookup key that
|
||||||
// does not overwrite existing bridges could become an issue. We keep a list
|
// does not overwrite existing bridges could become an issue.We keep a list
|
||||||
// of recycleable lookup keys from buckets that have been removed and prioritize
|
// of recycleable lookup keys from buckets that have been removed and prioritize
|
||||||
// this list before increasing the counter
|
// this list before increasing the counter
|
||||||
fn find_next_available_key(&mut self, bdb: &mut BridgeDb) -> Result<u32, NoAvailableIDError> {
|
fn find_next_available_key(&mut self, bdb: &mut BridgeDb) -> Result<u32, NoAvailableIDError> {
|
||||||
|
@ -728,6 +744,7 @@ impl BridgeAuth {
|
||||||
self.clean_up_open_entry(bdb);
|
self.clean_up_open_entry(bdb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Cleans up exipred blocked buckets
|
||||||
fn clean_up_blocked(&mut self) {
|
fn clean_up_blocked(&mut self) {
|
||||||
if !self.bridge_table.blocked_keys.is_empty()
|
if !self.bridge_table.blocked_keys.is_empty()
|
||||||
&& self
|
&& self
|
||||||
|
@ -754,7 +771,7 @@ impl BridgeAuth {
|
||||||
if bridgeline.port > 0 {
|
if bridgeline.port > 0 {
|
||||||
// Move to unallocated bridges
|
// Move to unallocated bridges
|
||||||
self.bridge_table.unallocated_bridges.push(*bridgeline);
|
self.bridge_table.unallocated_bridges.push(*bridgeline);
|
||||||
// Check if it's still in the reachable bridges. It should be if we've gotten this far.
|
// Check if it's still in the reachable bridges.It should be if we've gotten this far.
|
||||||
if let Some(_reachable_indexes_for_bridgeline) =
|
if let Some(_reachable_indexes_for_bridgeline) =
|
||||||
self.bridge_table.reachable.get(bridgeline)
|
self.bridge_table.reachable.get(bridgeline)
|
||||||
{
|
{
|
||||||
|
@ -780,6 +797,7 @@ impl BridgeAuth {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Cleans up expired open invitation buckets
|
||||||
fn clean_up_open_entry(&mut self, bdb: &mut BridgeDb) {
|
fn clean_up_open_entry(&mut self, bdb: &mut BridgeDb) {
|
||||||
// First check if there are any open invitation indexes that are old enough to be replaced
|
// First check if there are any open invitation indexes that are old enough to be replaced
|
||||||
if !self.bridge_table.open_inv_keys.is_empty()
|
if !self.bridge_table.open_inv_keys.is_empty()
|
||||||
|
@ -825,14 +843,14 @@ impl BridgeAuth {
|
||||||
self.time_offset += time::Duration::days(1);
|
self.time_offset += time::Duration::days(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[cfg(test)]
|
///#[cfg(test)]
|
||||||
/// For testing only: manually advance the day by the given number
|
/// For testing only: manually advance the day by the given number
|
||||||
/// of days
|
/// of days
|
||||||
pub fn advance_days(&mut self, days: u16) {
|
pub fn advance_days(&mut self, days: u16) {
|
||||||
self.time_offset += time::Duration::days(days.into());
|
self.time_offset += time::Duration::days(days.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get today's (real or simulated) date
|
/// Get today's (real or simulated) date as u32
|
||||||
pub fn today(&self) -> u32 {
|
pub fn today(&self) -> u32 {
|
||||||
// We will not encounter negative Julian dates (~6700 years ago)
|
// We will not encounter negative Julian dates (~6700 years ago)
|
||||||
// or ones larger than 32 bits
|
// or ones larger than 32 bits
|
||||||
|
@ -842,7 +860,7 @@ impl BridgeAuth {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get today's (real or simulated) date
|
/// Get today's (real or simulated) date as a DateTime<Utc> value
|
||||||
pub fn today_date(&self) -> DateTime<Utc> {
|
pub fn today_date(&self) -> DateTime<Utc> {
|
||||||
Utc::now()
|
Utc::now()
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ rust-version = "1.65"
|
||||||
homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home"
|
homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home"
|
||||||
description = "General helpers used by Lox"
|
description = "General helpers used by Lox"
|
||||||
keywords = ["tor", "lox"]
|
keywords = ["tor", "lox"]
|
||||||
# We must put *something* here and this will do
|
|
||||||
categories = ["rust-patterns"]
|
categories = ["rust-patterns"]
|
||||||
repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox.git/"
|
repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox.git/"
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ categories = ["api-bindings", "encoding"]
|
||||||
repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/tree/main/crates/rdsys-backend-api"
|
repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/tree/main/crates/rdsys-backend-api"
|
||||||
readme = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/blob/main/crates/rdsys-backend-api/README.md"
|
readme = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/blob/main/crates/rdsys-backend-api/README.md"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
|
Loading…
Reference in New Issue