Fixup and add comments, README to Lox Library
This commit is contained in:
parent
73b04b9a19
commit
e356034dae
|
@ -9,10 +9,10 @@
|
|||
},
|
||||
"rtype": {
|
||||
"endpoint": "http://127.0.0.1:7100/resources",
|
||||
"name": "https",
|
||||
"token": "HttpsApiTokenPlaceholder",
|
||||
"name": "lox",
|
||||
"token": "LoxApiTokenPlaceholder",
|
||||
"types": [
|
||||
"obfs2",
|
||||
"obfs4",
|
||||
"scramblesuit"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,8 +1,40 @@
|
|||
# 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 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).
|
||||
|
|
|
@ -240,41 +240,46 @@ struct K {
|
|||
|
||||
/// A BridgeTable is the internal structure holding the buckets
|
||||
/// containing the bridges, the keys used to encrypt the buckets, and
|
||||
/// the encrypted buckets. The encrypted buckets will be exposed to the
|
||||
/// the encrypted buckets. The encrypted buckets will be exposed to the
|
||||
/// users of the system, and each user credential will contain the
|
||||
/// decryption key for one bucket.
|
||||
#[serde_as]
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct BridgeTable {
|
||||
// All structures in the bridgetable are indexed by counter
|
||||
/// All structures in the bridgetable are indexed by counter
|
||||
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]>,
|
||||
/// 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 encbuckets: HashMap<u32, EncryptedBucket>,
|
||||
/// Individual bridges that are reachable
|
||||
/// Individual bridges that are reachable.
|
||||
#[serde_as(as = "HashMap<serde_with::json::JsonString, _>")]
|
||||
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
|
||||
/// 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.
|
||||
pub spares: HashSet<u32>,
|
||||
/// In some instances a single bridge may need to be added to a bucket
|
||||
/// In that case, a spare bucket will be removed from the set of spare bridges. One
|
||||
/// In some instances a single bridge may need to be added to a bucket as a replacement
|
||||
/// 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>,
|
||||
// To prevent issues with a counter for the hashmap keys, we keep a list of keys that
|
||||
// no longer match any buckets that can be used before increasing the counter
|
||||
// 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.
|
||||
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
|
||||
// buckets after the EXPIRY_DATE
|
||||
// buckets after the EXPIRY_DATE.
|
||||
pub blocked_keys: Vec<(u32, u32)>,
|
||||
// Similarly, we maintain 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
|
||||
// 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.
|
||||
// TODO: add open entry buckets to the open_inv_keys only once they have been distributed
|
||||
pub open_inv_keys: Vec<(u32, u32)>,
|
||||
/// 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.
|
||||
pub date_last_enc: u32,
|
||||
}
|
||||
|
@ -288,7 +293,7 @@ impl BridgeTable {
|
|||
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]) {
|
||||
// Pick a random key to encrypt this bucket
|
||||
let mut rng = rand::thread_rng();
|
||||
|
@ -311,7 +316,7 @@ impl BridgeTable {
|
|||
}
|
||||
|
||||
/// Create the vector of encrypted buckets from the keys and buckets
|
||||
/// in the BridgeTable. All of the entries will be (randomly)
|
||||
/// in the BridgeTable. All of the entries will be (randomly)
|
||||
/// re-encrypted, so it will be hidden whether any individual bucket
|
||||
/// has changed (except for entirely new buckets, of course).
|
||||
/// Bucket Reachability credentials are added to the buckets when
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*! The various credentials used by the system.
|
||||
|
||||
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
|
||||
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::scalar::Scalar;
|
||||
|
@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
|
|||
/// A migration credential.
|
||||
///
|
||||
/// This credential authorizes the holder of the Lox credential with the
|
||||
/// given id to switch from bucket from_bucket to bucket to_bucket. The
|
||||
/// given id to switch from bucket from_bucket to bucket to_bucket. The
|
||||
/// migration_type attribute is 0 for trust upgrade migrations (moving
|
||||
/// from a 1-bridge untrusted bucket to a 3-bridge trusted bucket) and 1
|
||||
/// for blockage migrations (moving buckets because the from_bucket has
|
||||
|
@ -29,7 +29,7 @@ pub struct Migration {
|
|||
/// The main user credential in the Lox system.
|
||||
///
|
||||
/// Its id is jointly generated by the user and the BA (bridge
|
||||
/// authority), but known only to the user. The level_since date is the
|
||||
/// authority), but known only to the user. The level_since date is the
|
||||
/// Julian date of when this user was changed to the current trust
|
||||
/// level.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
@ -46,13 +46,13 @@ pub struct Lox {
|
|||
|
||||
/// The migration key credential.
|
||||
///
|
||||
/// This credential is never actually instantiated. It is an implicit
|
||||
/// credential on attributes lox_id and from_bucket. This credential
|
||||
/// type does have an associated private and public key, however. The
|
||||
/// This credential is never actually instantiated. It is an implicit
|
||||
/// credential on attributes lox_id and from_bucket. This credential
|
||||
/// type does have an associated private and public key, however. The
|
||||
/// idea is that if a user proves (in zero knowledge) that their Lox
|
||||
/// credential entitles them to migrate from one bucket to another, the
|
||||
/// BA will issue a (blinded, so the BA will not know the values of the
|
||||
/// attributes or of Q) MAC on this implicit credential. The Q value
|
||||
/// attributes or of Q) MAC on this implicit credential. The Q value
|
||||
/// will then be used (actually, a hash of lox_id, from_bucket, and Q)
|
||||
/// to encrypt the to_bucket, P, and Q fields of a Migration credential.
|
||||
/// That way, people entitled to migrate buckets can receive a Migration
|
||||
|
@ -70,7 +70,7 @@ pub struct MigrationKey {
|
|||
///
|
||||
/// Each day, a credential of this type is put in each bucket that has
|
||||
/// at least a (configurable) threshold number of bridges that have not
|
||||
/// been blocked as of the given date. Users can present this
|
||||
/// been blocked as of the given date. Users can present this
|
||||
/// credential (in zero knowledge) with today's date to prove that the
|
||||
/// bridges in their bucket have not been blocked, in order to gain a
|
||||
/// trust level.
|
||||
|
@ -86,7 +86,7 @@ pub struct BucketReachability {
|
|||
///
|
||||
/// These credentials allow a Lox user (the inviter) of sufficient trust
|
||||
/// (level 2 or higher) to invite someone else (the invitee) to join the
|
||||
/// system. The invitee ends up at trust level 1, in the _same bucket_
|
||||
/// system. The invitee ends up at trust level 1, in the _same bucket_
|
||||
/// as the inviter, and inherits the inviter's blockages count (so that
|
||||
/// you can't clear your blockages count simply by inviting yourself).
|
||||
/// Invitations expire after some amount of time.
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::hash::Hash;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Each instance of DupFilter maintains its own independent table of
|
||||
/// seen ids. IdType will typically be Scalar.
|
||||
/// seen ids. IdType will typically be Scalar.
|
||||
#[derive(Default, Debug, Serialize, Deserialize)]
|
||||
pub struct DupFilter<IdType: Hash + Eq + Copy + Serialize> {
|
||||
seen_table: HashSet<IdType>,
|
||||
|
|
|
@ -8,7 +8,7 @@ Keyed-Verification Anonymous Credentials" (Chase, Meiklejohn, and
|
|||
Zaverucha, CCS 2014)
|
||||
|
||||
The notation follows that of the paper "Hyphae: Social Secret Sharing"
|
||||
(Lovecruft and de Valence, 2017), Section 4. */
|
||||
(Lovecruft and de Valence, 2017), Section 4. */
|
||||
|
||||
// We really want points to be capital letters and scalars to be
|
||||
// lowercase letters
|
||||
|
@ -62,10 +62,12 @@ lazy_static! {
|
|||
}
|
||||
|
||||
// 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
|
||||
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)]
|
||||
pub enum ReplaceSuccess {
|
||||
NotFound = 0,
|
||||
|
@ -73,18 +75,23 @@ pub enum ReplaceSuccess {
|
|||
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)]
|
||||
pub enum NoAvailableIDError {
|
||||
#[error("Find key exhausted with no available index found!")]
|
||||
ExhaustedIndexer,
|
||||
}
|
||||
|
||||
/// This error is thrown after the MAX_DAILY_BRIDGES threshold for bridges
|
||||
/// distributed in a day has been reached
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ExceededMaxBridgesError {
|
||||
#[error("The maximum number of bridges has already been distributed today, please try again tomorrow!")]
|
||||
ExceededMaxBridges,
|
||||
}
|
||||
|
||||
/// Private Key of the Issuer
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct IssuerPrivKey {
|
||||
x0tilde: Scalar,
|
||||
|
@ -106,11 +113,13 @@ impl IssuerPrivKey {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct IssuerPubKey {
|
||||
X: Vec<RistrettoPoint>,
|
||||
}
|
||||
|
||||
/// Public Key of the Issuer
|
||||
impl IssuerPubKey {
|
||||
/// Create an IssuerPubKey from the corresponding IssuerPrivKey
|
||||
pub fn new(privkey: &IssuerPrivKey) -> IssuerPubKey {
|
||||
|
@ -130,11 +139,11 @@ impl IssuerPubKey {
|
|||
}
|
||||
}
|
||||
|
||||
// Number of times a given invitation is ditributed
|
||||
/// Number of times a given invitation is ditributed
|
||||
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;
|
||||
/// 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
|
||||
/// people who are not yet part of the system.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
@ -188,6 +197,8 @@ impl BridgeDb {
|
|||
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) {
|
||||
if self.openinv_buckets.contains(bucket) {
|
||||
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) {
|
||||
self.distributed_buckets.push(bucket);
|
||||
}
|
||||
|
@ -239,8 +251,8 @@ impl BridgeDb {
|
|||
}
|
||||
}
|
||||
|
||||
/// Verify an open invitation. Returns the invitation id and the
|
||||
/// bucket number if the signature checked out. It is up to the
|
||||
/// Verify an open invitation. Returns the invitation id and the
|
||||
/// bucket number if the signature checked out. It is up to the
|
||||
/// caller to then check that the invitation id has not been used
|
||||
/// before.
|
||||
pub fn verify(
|
||||
|
@ -250,7 +262,7 @@ impl BridgeDb {
|
|||
// Pull out the signature and verify it
|
||||
let sig = Signature::try_from(&invitation[(32 + 4)..])?;
|
||||
pubkey.verify(&invitation[0..(32 + 4)], &sig)?;
|
||||
// The signature passed. Pull out the bucket number and then
|
||||
// The signature passed. Pull out the bucket number and then
|
||||
// the invitation id
|
||||
let bucket = u32::from_le_bytes(invitation[32..(32 + 4)].try_into().unwrap());
|
||||
let s = Scalar::from_canonical_bytes(invitation[0..32].try_into().unwrap());
|
||||
|
@ -270,7 +282,7 @@ impl Default for BridgeDb {
|
|||
}
|
||||
}
|
||||
|
||||
/// The bridge authority. This will typically be a singleton object.
|
||||
/// The bridge authority. This will typically be a singleton object.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct BridgeAuth {
|
||||
/// The private key for the main Lox credential
|
||||
|
@ -363,7 +375,7 @@ impl BridgeAuth {
|
|||
/// Insert a set of open invitation bridges.
|
||||
///
|
||||
/// Each of the bridges will be given its own open invitation
|
||||
/// bucket, and the BridgeDb will be informed. A single bucket
|
||||
/// bucket, and the BridgeDb will be informed. A single bucket
|
||||
/// containing all of the bridges will also be created, with a trust
|
||||
/// upgrade migration from each of the single-bridge buckets.
|
||||
pub fn add_openinv_bridges(
|
||||
|
@ -406,6 +418,9 @@ impl BridgeAuth {
|
|||
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(
|
||||
&mut self,
|
||||
accounted_for_bridges: Vec<u64>,
|
||||
|
@ -419,6 +434,7 @@ impl BridgeAuth {
|
|||
unaccounted_for
|
||||
}
|
||||
|
||||
/// Allocate single left over bridges to an open invitation bucket
|
||||
pub fn allocate_bridges(
|
||||
&mut self,
|
||||
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
|
||||
// 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
|
||||
// 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
|
||||
pub fn bridge_update(&mut self, bridge: &BridgeLine) -> bool {
|
||||
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();
|
||||
for reachable_bridge in reachable_bridges {
|
||||
if reachable_bridge.0.uid_fingerprint == bridge.uid_fingerprint {
|
||||
|
@ -490,6 +504,8 @@ impl BridgeAuth {
|
|||
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(
|
||||
&mut self,
|
||||
bridge: &BridgeLine,
|
||||
|
@ -591,13 +607,13 @@ impl BridgeAuth {
|
|||
/// Mark a bridge as unreachable
|
||||
///
|
||||
/// This bridge will be removed from each of the buckets that
|
||||
/// contains it. If any of those are open-invitation buckets, the
|
||||
/// contains it. If any of those are open-invitation buckets, the
|
||||
/// trust upgrade migration for that bucket will be removed and the
|
||||
/// BridgeDb will be informed to stop handing out that bridge. If
|
||||
/// BridgeDb will be informed to stop handing out that bridge. If
|
||||
/// any of those are trusted buckets where the number of reachable
|
||||
/// bridges has fallen below the threshold, a blockage migration
|
||||
/// from that bucket to a spare bucket will be added, and the spare
|
||||
/// bucket will be removed from the list of hot spares. In
|
||||
/// bucket will be removed from the list of hot spares. In
|
||||
/// addition, if the blocked bucket was the _target_ of a blockage
|
||||
/// migration, change the target to the new (formerly spare) bucket.
|
||||
/// Returns true if sucessful, or false if it needed a hot spare but
|
||||
|
@ -647,9 +663,9 @@ impl BridgeAuth {
|
|||
continue;
|
||||
}
|
||||
|
||||
// This bucket is now unreachable. Get a spare bucket
|
||||
// This bucket is now unreachable. Get a spare bucket
|
||||
if self.bridge_table.spares.is_empty() {
|
||||
// Uh, oh. No spares available. Just delete any
|
||||
// Uh, oh. No spares available. Just delete any
|
||||
// migrations leading to this bucket.
|
||||
res = false;
|
||||
self.trustup_migration_table
|
||||
|
@ -692,7 +708,7 @@ impl BridgeAuth {
|
|||
}
|
||||
|
||||
// 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
|
||||
// this list before increasing the counter
|
||||
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);
|
||||
}
|
||||
|
||||
/// Cleans up exipred blocked buckets
|
||||
fn clean_up_blocked(&mut self) {
|
||||
if !self.bridge_table.blocked_keys.is_empty()
|
||||
&& self
|
||||
|
@ -754,7 +771,7 @@ impl BridgeAuth {
|
|||
if bridgeline.port > 0 {
|
||||
// Move to unallocated bridges
|
||||
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) =
|
||||
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) {
|
||||
// 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()
|
||||
|
@ -825,14 +843,14 @@ impl BridgeAuth {
|
|||
self.time_offset += time::Duration::days(1);
|
||||
}
|
||||
|
||||
//#[cfg(test)]
|
||||
///#[cfg(test)]
|
||||
/// For testing only: manually advance the day by the given number
|
||||
/// of days
|
||||
pub fn advance_days(&mut self, days: u16) {
|
||||
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 {
|
||||
// We will not encounter negative Julian dates (~6700 years ago)
|
||||
// or ones larger than 32 bits
|
||||
|
@ -842,7 +860,7 @@ impl BridgeAuth {
|
|||
.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> {
|
||||
Utc::now()
|
||||
}
|
||||
|
@ -961,13 +979,13 @@ pub fn pt_dbl(P: &RistrettoPoint) -> RistrettoPoint {
|
|||
|
||||
/// The protocol modules.
|
||||
///
|
||||
/// Each protocol lives in a submodule. Each submodule defines structs
|
||||
/// Each protocol lives in a submodule. Each submodule defines structs
|
||||
/// for Request (the message from the client to the bridge authority),
|
||||
/// State (the state held by the client while waiting for the reply),
|
||||
/// and Response (the message from the bridge authority to the client).
|
||||
/// Each submodule defines functions request, which produces a (Request,
|
||||
/// State) pair, and handle_response, which consumes a State and a
|
||||
/// Response. It also adds a handle_* function to the BridgeAuth struct
|
||||
/// Response. It also adds a handle_* function to the BridgeAuth struct
|
||||
/// that consumes a Request and produces a Result<Response, ProofError>.
|
||||
pub mod proto {
|
||||
pub mod blockage_migration;
|
||||
|
|
|
@ -7,7 +7,6 @@ rust-version = "1.65"
|
|||
homepage = "https://gitlab.torproject.org/tpo/anti-censorship/lox/-/wikis/home"
|
||||
description = "General helpers used by Lox"
|
||||
keywords = ["tor", "lox"]
|
||||
# We must put *something* here and this will do
|
||||
categories = ["rust-patterns"]
|
||||
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"
|
||||
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]
|
||||
serde_json = "1"
|
||||
|
|
Loading…
Reference in New Issue