From faf40caf3aaeb4cf8577c28a7b20d01cc0372e89 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Tue, 25 Jul 2023 17:24:03 -0400 Subject: [PATCH] Change open invite logic to distribute to k users --- crates/lox-distributor/src/lox_context.rs | 2 +- crates/lox-library/src/lib.rs | 50 ++++++++++++++++++----- crates/lox-library/src/tests.rs | 8 ++-- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/crates/lox-distributor/src/lox_context.rs b/crates/lox-distributor/src/lox_context.rs index 5f6a3b9..50a6696 100644 --- a/crates/lox-distributor/src/lox_context.rs +++ b/crates/lox-distributor/src/lox_context.rs @@ -140,7 +140,7 @@ impl LoxServerContext { } fn gen_invite(&self) -> lox_utils::Invite { - let obj = self.db.lock().unwrap(); + let mut obj = self.db.lock().unwrap(); lox_utils::Invite { invite: obj.invite(), } diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 2704c0e..8a5de08 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -123,6 +123,7 @@ impl IssuerPubKey { } } +pub const OPENINV_K: u32 = 10; /// 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. @@ -134,6 +135,8 @@ pub struct BridgeDb { pub pubkey: PublicKey, /// The set of open-invitation buckets openinv_buckets: HashSet, + distributed_buckets: Vec, + current_k: u32, } /// An open invitation is a [u8; OPENINV_LENGTH] where the first 32 @@ -155,6 +158,8 @@ impl BridgeDb { keypair, pubkey, openinv_buckets: Default::default(), + distributed_buckets: Default::default(), + current_k: 0, } } @@ -168,18 +173,41 @@ impl BridgeDb { self.openinv_buckets.remove(bucket); } - /// Produce an open invitation. In this example code, we just - /// choose a random open-invitation bucket. - pub fn invite(&self) -> [u8; OPENINV_LENGTH] { + 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!"); + self.openinv_buckets.remove(bucket); + } else if self.distributed_buckets.contains(bucket) { + self.distributed_buckets.retain(|&x| x != *bucket); + } + } + + pub fn mark_distributed(&mut self, bucket: u32) { + self.distributed_buckets.push(bucket); + } + + /// Produce an open invitation such that the next k users, where k is < + /// OPENINV_K, will receive the same open invitation bucket + /// chosen randomly from the set of open-invitation buckets. + pub fn invite(&mut self) -> [u8; OPENINV_LENGTH] { let mut res: [u8; OPENINV_LENGTH] = [0; OPENINV_LENGTH]; let mut rng = rand::thread_rng(); // Choose a random invitation id (a Scalar) and serialize it let id = Scalar::random(&mut rng); res[0..32].copy_from_slice(&id.to_bytes()); - // Choose a random bucket number (from the set of open - // invitation buckets) and serialize it - let openinv_vec: Vec<&u32> = self.openinv_buckets.iter().collect(); - let bucket_num = *openinv_vec[rng.gen_range(0, openinv_vec.len())]; + let bucket_num: u32; + if self.current_k < OPENINV_K && !self.distributed_buckets.is_empty() { + bucket_num = *self.distributed_buckets.last().unwrap(); + self.current_k += 1; + } else { + // Choose a random bucket number (from the set of open + // invitation buckets) and serialize it + let openinv_vec: Vec<&u32> = self.openinv_buckets.iter().collect(); + bucket_num = *openinv_vec[rng.gen_range(0, openinv_vec.len())]; + self.mark_distributed(bucket_num); + self.remove_openinv(&bucket_num); + self.current_k = 1; + } res[32..(32 + 4)].copy_from_slice(&bucket_num.to_le_bytes()); // Sign the first 36 bytes and serialize it let sig = self.keypair.sign(&res[0..(32 + 4)]); @@ -583,8 +611,10 @@ impl BridgeAuth { bucket[*offset] = BridgeLine::default(); // Is this bucket an open-invitation bucket? - if bdb.openinv_buckets.contains(bucketnum) { - bdb.remove_openinv(bucketnum); + if bdb.openinv_buckets.contains(bucketnum) + || bdb.distributed_buckets.contains(bucketnum) + { + bdb.remove_blocked_or_expired_buckets(bucketnum); self.trustup_migration_table.table.remove(bucketnum); continue; } @@ -747,7 +777,7 @@ impl BridgeAuth { .partition(|&x| x.1 + EXPIRY_DATE < self.today()); for item in expired { let new_item = item.0; - bdb.remove_openinv(&new_item); + bdb.remove_blocked_or_expired_buckets(&new_item); // Remove any trust upgrade migrations from this // bucket self.trustup_migration_table diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 1738242..08482aa 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -731,10 +731,6 @@ fn test_clean_up_open_entry() { // Add new bridges to trigger bucket cleanup let _ = th.ba.add_openinv_bridges(bucket, &mut th.bdb); } - println!( - "The number of trustup migrations after adding 10 new buckets is: {:?}", - th.ba.trustup_migration_table.table.len() - ); assert!( th.ba.trustup_migration_table.table.len() == 30, "There should be 10*3 eligible trust up migrations" @@ -861,7 +857,9 @@ fn block_bridges(th: &mut TestHarness, to_block: usize) { while block_index.len() < to_block { let rand_num = rng.gen_range(1, blockable_range); - if !th.bdb.openinv_buckets.contains(&(rand_num as u32)) && !block_index.contains(&rand_num) + if !th.bdb.openinv_buckets.contains(&(rand_num as u32)) + && !th.bdb.distributed_buckets.contains(&(rand_num as u32)) + && !block_index.contains(&rand_num) { block_index.insert(rand_num); }