From e079a361ba84c2c5daba4e5c90ed7d89879f68a8 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Mon, 26 Apr 2021 22:44:59 -0400 Subject: [PATCH 001/115] A simple BridgeDb to create open invitations --- crates/lox-library/Cargo.toml | 22 ++++ crates/lox-library/src/lib.rs | 164 ++++++++++++++++++++++++++++++ crates/lox-library/tests/tests.rs | 10 ++ 3 files changed, 196 insertions(+) create mode 100644 crates/lox-library/Cargo.toml create mode 100644 crates/lox-library/src/lib.rs create mode 100644 crates/lox-library/tests/tests.rs diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml new file mode 100644 index 0000000..5d4eab2 --- /dev/null +++ b/crates/lox-library/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "lox" +version = "0.1.0" +authors = ["Ian Goldberg "] +edition = "2018" + +[dependencies] +curve25519-dalek = { package = "curve25519-dalek-ng", version = "3", default-features = false, features = ["serde", "std"] } +ed25519-dalek = "1" +zkp = "0.8" +bincode = "1" +rand = "0.7" +serde = "1" +sha2 = "0.9" +lazy_static = "1" +hex_fmt = "0.3" + +[features] +default = ["u64_backend"] +u32_backend = ["curve25519-dalek/u32_backend"] +u64_backend = ["curve25519-dalek/u64_backend"] +simd_backend = ["curve25519-dalek/simd_backend"] diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs new file mode 100644 index 0000000..ad541d7 --- /dev/null +++ b/crates/lox-library/src/lib.rs @@ -0,0 +1,164 @@ +/*! Implementation of a new style of bridge authority for Tor that +allows users to invite other users, while protecting the social graph +from the bridge authority itself. + +We use CMZ14 credentials (GGM version, which is more efficient, but +makes a stronger security assumption): "Algebraic MACs and +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. */ + +// We really want points to be capital letters and scalars to be +// lowercase letters +#![allow(non_snake_case)] + +#[macro_use] +extern crate zkp; + +use sha2::Sha512; + +use rand::rngs::OsRng; +use rand::RngCore; +use std::convert::{TryFrom, TryInto}; + +use curve25519_dalek::constants as dalek_constants; +use curve25519_dalek::ristretto::RistrettoBasepointTable; +use curve25519_dalek::ristretto::RistrettoPoint; +use curve25519_dalek::scalar::Scalar; + +use ed25519_dalek::{Keypair, PublicKey, Signature, SignatureError, Signer, Verifier}; + +use lazy_static::lazy_static; + +lazy_static! { + pub static ref CMZ_A: RistrettoPoint = + RistrettoPoint::hash_from_bytes::(b"CMZ Generator A"); + pub static ref CMZ_B: RistrettoPoint = dalek_constants::RISTRETTO_BASEPOINT_POINT; + pub static ref CMZ_A_TABLE: RistrettoBasepointTable = RistrettoBasepointTable::create(&CMZ_A); + pub static ref CMZ_B_TABLE: RistrettoBasepointTable = + dalek_constants::RISTRETTO_BASEPOINT_TABLE; +} + +#[derive(Clone, Debug)] +pub struct IssuerPrivKey { + x0tilde: Scalar, + x: Vec, +} + +impl IssuerPrivKey { + /// Create an IssuerPrivKey for credentials with the given number of + /// attributes. + pub fn new(n: u16) -> IssuerPrivKey { + let mut rng = rand::thread_rng(); + let x0tilde = Scalar::random(&mut rng); + let mut x: Vec = Vec::with_capacity((n + 1) as usize); + + // Set x to a vector of n+1 random Scalars + x.resize_with((n + 1) as usize, || Scalar::random(&mut rng)); + + IssuerPrivKey { x0tilde, x } + } +} + +#[derive(Clone, Debug)] +pub struct IssuerPubKey { + X: Vec, +} + +impl IssuerPubKey { + /// Create an IssuerPubKey from the corresponding IssuerPrivKey + pub fn new(privkey: &IssuerPrivKey) -> IssuerPubKey { + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + let n_plus_one = privkey.x.len(); + let mut X: Vec = Vec::with_capacity(n_plus_one); + + // The first element is a special case; it is + // X[0] = x0tilde*A + x[0]*B + X.push(&privkey.x0tilde * Atable + &privkey.x[0] * Btable); + + // The other elements (1 through n) are X[i] = x[i]*A + for i in 1..n_plus_one { + X.push(&privkey.x[i] * Atable); + } + IssuerPubKey { X } + } +} + +/// 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)] +pub struct BridgeDb { + /// The keypair for signing open invitations + keypair: Keypair, + /// The public key for verifying open invitations + pub pubkey: PublicKey, + /// The number of open-invitation buckets + num_openinv_buckets: u32, +} + +/// An open invitation is a [u8; OPENINV_LENGTH] where the first 32 +/// bytes are the serialization of a random Scalar (the invitation id), +/// the next 4 bytes are a little-endian bucket number, and the last +/// SIGNATURE_LENGTH bytes are the signature on the first 36 bytes. +pub const OPENINV_LENGTH: usize = 32 // the length of the random + // invitation id (a Scalar) + + 4 // the length of the u32 for the bucket number + + ed25519_dalek::SIGNATURE_LENGTH; // the length of the signature + +impl BridgeDb { + /// Create the BridgeDb. + pub fn new(num_openinv_buckets: u32) -> BridgeDb { + let mut csprng = OsRng {}; + let keypair = Keypair::generate(&mut csprng); + let pubkey = keypair.public; + BridgeDb { + keypair, + pubkey, + num_openinv_buckets, + } + } + + /// Produce an open invitation. In this example code, we just + /// choose a random open-invitation bucket. + pub fn invite(&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 (mod num_openinv_buckets) and + // serialize it + let bucket_num = rng.next_u32() % self.num_openinv_buckets; + 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)]); + res[(32 + 4)..].copy_from_slice(&sig.to_bytes()); + res + } + + /// 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( + invitation: [u8; OPENINV_LENGTH], + pubkey: PublicKey, + ) -> Result<(Scalar, u32), SignatureError> { + // 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 invitation id + let bucket = u32::from_le_bytes(invitation[32..(32 + 4)].try_into().unwrap()); + match Scalar::from_canonical_bytes(invitation[0..32].try_into().unwrap()) { + // It should never happen that there's a valid signature on + // an invalid serialization of a Scalar, but check anyway. + None => Err(SignatureError::new()), + Some(s) => Ok((s, bucket)), + } + } +} diff --git a/crates/lox-library/tests/tests.rs b/crates/lox-library/tests/tests.rs new file mode 100644 index 0000000..1373662 --- /dev/null +++ b/crates/lox-library/tests/tests.rs @@ -0,0 +1,10 @@ +use lox::BridgeDb; + +#[test] +fn test_openinvite() { + let bdb = BridgeDb::new(20); + let inv = bdb.invite(); + println!("{:?}", inv); + let res = BridgeDb::verify(inv, bdb.pubkey); + println!("{:?}", res); +} From 23d66aaae301e03bd34480bfcde4c7eceffb6dea Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Tue, 27 Apr 2021 07:20:53 -0400 Subject: [PATCH 002/115] A simple duplicate filter for filtering shows of duplicate ids --- crates/lox-library/src/dup_filter.rs | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 crates/lox-library/src/dup_filter.rs diff --git a/crates/lox-library/src/dup_filter.rs b/crates/lox-library/src/dup_filter.rs new file mode 100644 index 0000000..48681ed --- /dev/null +++ b/crates/lox-library/src/dup_filter.rs @@ -0,0 +1,34 @@ +/*! Filter duplicate shows of credentials and open invitations by id + * (which will typically be a Scalar). This implementation just keeps + * the table of seen ids in memory, but a production one would of course + * use a disk-backed database. */ + +use std::collections::HashMap; +use std::hash::Hash; +use std::cmp::Eq; + +/// Each instance of DupFilter maintains its own independent table of +/// seen ids. IdType will typically be Scalar. +#[derive(Default,Debug)] +pub struct DupFilter { + seen_table: HashMap, +} + +impl DupFilter { + /// Check to see if the id is in the seen table, but do not add it + /// to the seen table. Return true if it is already in the table, + /// false if not. + pub fn check(&self, id: &IdType) -> bool { + self.seen_table.contains_key(id) + } + + /// As atomically as possible, check to see if the id is in the seen + /// table, and add it if not. Return Ok(()) if it was not already + /// in the table, and Err(()) if it was. + pub fn filter(&mut self, id: &IdType) -> Result<(),()> { + match self.seen_table.insert(*id, ()) { + None => Ok(()), + Some(()) => Err(()), + } + } +} From befacce4ef2a9743c496615213efc962dd9d7d34 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Tue, 27 Apr 2021 08:53:22 -0400 Subject: [PATCH 003/115] test for dup_filter module --- crates/lox-library/src/dup_filter.rs | 6 ++--- crates/lox-library/src/lib.rs | 2 ++ crates/lox-library/tests/tests.rs | 35 ++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/crates/lox-library/src/dup_filter.rs b/crates/lox-library/src/dup_filter.rs index 48681ed..72f00df 100644 --- a/crates/lox-library/src/dup_filter.rs +++ b/crates/lox-library/src/dup_filter.rs @@ -3,13 +3,13 @@ * the table of seen ids in memory, but a production one would of course * use a disk-backed database. */ +use std::cmp::Eq; use std::collections::HashMap; use std::hash::Hash; -use std::cmp::Eq; /// Each instance of DupFilter maintains its own independent table of /// seen ids. IdType will typically be Scalar. -#[derive(Default,Debug)] +#[derive(Default, Debug)] pub struct DupFilter { seen_table: HashMap, } @@ -25,7 +25,7 @@ impl DupFilter { /// As atomically as possible, check to see if the id is in the seen /// table, and add it if not. Return Ok(()) if it was not already /// in the table, and Err(()) if it was. - pub fn filter(&mut self, id: &IdType) -> Result<(),()> { + pub fn filter(&mut self, id: &IdType) -> Result<(), ()> { match self.seen_table.insert(*id, ()) { None => Ok(()), Some(()) => Err(()), diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index ad541d7..dc17633 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -17,6 +17,8 @@ The notation follows that of the paper "Hyphae: Social Secret Sharing" #[macro_use] extern crate zkp; +pub mod dup_filter; + use sha2::Sha512; use rand::rngs::OsRng; diff --git a/crates/lox-library/tests/tests.rs b/crates/lox-library/tests/tests.rs index 1373662..ad6bc4b 100644 --- a/crates/lox-library/tests/tests.rs +++ b/crates/lox-library/tests/tests.rs @@ -1,5 +1,8 @@ +use lox::dup_filter; use lox::BridgeDb; +use curve25519_dalek::scalar::Scalar; + #[test] fn test_openinvite() { let bdb = BridgeDb::new(20); @@ -8,3 +11,35 @@ fn test_openinvite() { let res = BridgeDb::verify(inv, bdb.pubkey); println!("{:?}", res); } + +#[test] +fn test_dup_filter() { + let mut df1: dup_filter::DupFilter = Default::default(); + let mut df2: dup_filter::DupFilter = Default::default(); + let mut rng = rand::thread_rng(); + let s1 = Scalar::random(&mut rng); + let s2 = Scalar::random(&mut rng); + let s3 = Scalar::random(&mut rng); + let s4 = Scalar::random(&mut rng); + let s5 = Scalar::random(&mut rng); + // Check basic behaviour + assert_eq!(df1.check(&s1), false); + assert_eq!(df1.filter(&s1), Ok(())); + assert_eq!(df1.check(&s1), true); + assert_eq!(df1.filter(&s1), Err(())); + // Ensure different instances of DupFilter have different tables + assert_eq!(df2.check(&s1), false); + assert_eq!(df2.filter(&s1), Ok(())); + assert_eq!(df2.filter(&s1), Err(())); + assert_eq!(df2.check(&s1), true); + // Check multiple ids + assert_eq!(df1.check(&s2), false); + assert_eq!(df1.filter(&s3), Ok(())); + assert_eq!(df1.filter(&s4), Ok(())); + assert_eq!(df1.filter(&s3), Err(())); + assert_eq!(df1.check(&s1), true); + assert_eq!(df1.filter(&s1), Err(())); + assert_eq!(df1.filter(&s5), Ok(())); + println!("df1 = {:?}", df1); + println!("df2 = {:?}", df2); +} From f067c8b79a9f710fbc3075e76507fe9fb178c667 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Tue, 27 Apr 2021 12:59:29 -0400 Subject: [PATCH 004/115] Use a custom enum instead of Result<(),()> in DupFilter --- crates/lox-library/src/dup_filter.rs | 30 +++++++++++++++++++-------- crates/lox-library/tests/tests.rs | 31 ++++++++++++++-------------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/crates/lox-library/src/dup_filter.rs b/crates/lox-library/src/dup_filter.rs index 72f00df..b128261 100644 --- a/crates/lox-library/src/dup_filter.rs +++ b/crates/lox-library/src/dup_filter.rs @@ -14,21 +14,33 @@ pub struct DupFilter { seen_table: HashMap, } +/// A return type indicating whether the item was fresh (not previously +/// seen) or previously seen +#[derive(PartialEq, Eq, Debug)] +pub enum SeenType { + Fresh, + Seen, +} + impl DupFilter { /// Check to see if the id is in the seen table, but do not add it - /// to the seen table. Return true if it is already in the table, - /// false if not. - pub fn check(&self, id: &IdType) -> bool { - self.seen_table.contains_key(id) + /// to the seen table. Return Seen if it is already in the table, + /// Fresh if not. + pub fn check(&self, id: &IdType) -> SeenType { + if self.seen_table.contains_key(id) { + SeenType::Seen + } else { + SeenType::Fresh + } } /// As atomically as possible, check to see if the id is in the seen - /// table, and add it if not. Return Ok(()) if it was not already - /// in the table, and Err(()) if it was. - pub fn filter(&mut self, id: &IdType) -> Result<(), ()> { + /// table, and add it if not. Return Fresh if it was not already + /// in the table, and Seen if it was. + pub fn filter(&mut self, id: &IdType) -> SeenType { match self.seen_table.insert(*id, ()) { - None => Ok(()), - Some(()) => Err(()), + None => SeenType::Fresh, + Some(()) => SeenType::Seen, } } } diff --git a/crates/lox-library/tests/tests.rs b/crates/lox-library/tests/tests.rs index ad6bc4b..ce497fa 100644 --- a/crates/lox-library/tests/tests.rs +++ b/crates/lox-library/tests/tests.rs @@ -1,4 +1,5 @@ use lox::dup_filter; +use lox::dup_filter::SeenType::{Fresh, Seen}; use lox::BridgeDb; use curve25519_dalek::scalar::Scalar; @@ -23,23 +24,23 @@ fn test_dup_filter() { let s4 = Scalar::random(&mut rng); let s5 = Scalar::random(&mut rng); // Check basic behaviour - assert_eq!(df1.check(&s1), false); - assert_eq!(df1.filter(&s1), Ok(())); - assert_eq!(df1.check(&s1), true); - assert_eq!(df1.filter(&s1), Err(())); + assert_eq!(df1.check(&s1), Fresh); + assert_eq!(df1.filter(&s1), Fresh); + assert_eq!(df1.check(&s1), Seen); + assert_eq!(df1.filter(&s1), Seen); // Ensure different instances of DupFilter have different tables - assert_eq!(df2.check(&s1), false); - assert_eq!(df2.filter(&s1), Ok(())); - assert_eq!(df2.filter(&s1), Err(())); - assert_eq!(df2.check(&s1), true); + assert_eq!(df2.check(&s1), Fresh); + assert_eq!(df2.filter(&s1), Fresh); + assert_eq!(df2.filter(&s1), Seen); + assert_eq!(df2.check(&s1), Seen); // Check multiple ids - assert_eq!(df1.check(&s2), false); - assert_eq!(df1.filter(&s3), Ok(())); - assert_eq!(df1.filter(&s4), Ok(())); - assert_eq!(df1.filter(&s3), Err(())); - assert_eq!(df1.check(&s1), true); - assert_eq!(df1.filter(&s1), Err(())); - assert_eq!(df1.filter(&s5), Ok(())); + assert_eq!(df1.check(&s2), Fresh); + assert_eq!(df1.filter(&s3), Fresh); + assert_eq!(df1.filter(&s4), Fresh); + assert_eq!(df1.filter(&s3), Seen); + assert_eq!(df1.check(&s1), Seen); + assert_eq!(df1.filter(&s1), Seen); + assert_eq!(df1.filter(&s5), Fresh); println!("df1 = {:?}", df1); println!("df2 = {:?}", df2); } From beed9d95b297a7d652cac155b7ecfa03cdd6a208 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Tue, 27 Apr 2021 13:00:18 -0400 Subject: [PATCH 005/115] A basic encrypted bridge table --- crates/lox-library/Cargo.toml | 1 + crates/lox-library/src/bridge_table.rs | 157 +++++++++++++++++++++++++ crates/lox-library/src/lib.rs | 1 + 3 files changed, 159 insertions(+) create mode 100644 crates/lox-library/src/bridge_table.rs diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index 5d4eab2..388ae60 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -14,6 +14,7 @@ serde = "1" sha2 = "0.9" lazy_static = "1" hex_fmt = "0.3" +aes-gcm = "0.8" [features] default = ["u64_backend"] diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs new file mode 100644 index 0000000..6116857 --- /dev/null +++ b/crates/lox-library/src/bridge_table.rs @@ -0,0 +1,157 @@ +/*! The encrypted table of bridges. The table consists of a number of + * buckets, each holding some number (currently up to 3) of bridges. + * Each bucket is individually encrypted with a bucket key. Users will + * have a credential containing a bucket (number, key) combination, and + * so will be able to read one of the buckets. Users will either + * download the whole encrypted bucket list or use PIR to download a + * piece of it, so that the bridge authority does not learn which bucket + * the user has access to. */ + +use aes_gcm::aead; +use aes_gcm::aead::{generic_array::GenericArray, Aead, NewAead}; +use aes_gcm::Aes128Gcm; +use rand::RngCore; +use std::convert::TryInto; + +/// Each bridge information line is serialized into this many bytes +pub const BRIDGE_BYTES: usize = 128; + +/// The max number of bridges per bucket +pub const MAX_BRIDGES_PER_BUCKET: usize = 3; + +/// The size of a plaintext bucket +pub const BUCKET_BYTES: usize = BRIDGE_BYTES * MAX_BRIDGES_PER_BUCKET; + +/// The size of an encrypted bucket +pub const ENC_BUCKET_BYTES: usize = BUCKET_BYTES + 12 + 16; + +/// A bridge information line +#[derive(Debug)] +pub struct BridgeLine { + /// IPv4 or IPv6 address + pub addr: [u8; 16], + /// port + pub port: u16, + /// other protocol information, including pluggable trasport, public + /// key, etc. + pub info: [u8; BRIDGE_BYTES - 18], +} + +impl Default for BridgeLine { + /// An "empty" BridgeLine is represented by all zeros + fn default() -> Self { + Self { + addr: [0; 16], + port: 0, + info: [0; BRIDGE_BYTES - 18], + } + } +} + +impl BridgeLine { + /// Encode a BridgeLine to a byte array + pub fn encode(&self) -> [u8; BRIDGE_BYTES] { + let mut res: [u8; BRIDGE_BYTES] = [0; BRIDGE_BYTES]; + res[0..16].copy_from_slice(&self.addr); + res[16..18].copy_from_slice(&self.port.to_be_bytes()); + res[18..].copy_from_slice(&self.info); + res + } + /// Decode a BridgeLine from a byte array + pub fn decode(data: &[u8; BRIDGE_BYTES]) -> Self { + let mut res: Self = Default::default(); + res.addr.copy_from_slice(&data[0..16]); + res.port = u16::from_be_bytes(data[16..18].try_into().unwrap()); + res.info.copy_from_slice(&data[18..]); + res + } + /// Encode a bucket to a byte array + pub fn bucket_encode(bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET]) -> [u8; BUCKET_BYTES] { + let mut res: [u8; BUCKET_BYTES] = [0; BUCKET_BYTES]; + let mut pos: usize = 0; + for bridge in bucket { + res[pos..pos + BRIDGE_BYTES].copy_from_slice(&bridge.encode()); + pos += BRIDGE_BYTES; + } + res + } + /// Decode a bucket from a byte array + pub fn bucket_decode(data: &[u8; BUCKET_BYTES]) -> [BridgeLine; MAX_BRIDGES_PER_BUCKET] { + let mut pos: usize = 0; + let mut res: [BridgeLine; MAX_BRIDGES_PER_BUCKET] = Default::default(); + for bridge in res.iter_mut().take(MAX_BRIDGES_PER_BUCKET) { + *bridge = BridgeLine::decode(data[pos..pos + BRIDGE_BYTES].try_into().unwrap()); + pos += BRIDGE_BYTES; + } + res + } +} + +/// 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 +/// users of the system, and each user credential will contain the +/// decryption key for one bucket. +#[derive(Debug, Default)] +pub struct BridgeTable { + keys: Vec<[u8; 16]>, + buckets: Vec<[BridgeLine; MAX_BRIDGES_PER_BUCKET]>, + encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>, +} + +// Invariant: the lengths of the keys and buckets vectors are the same. +// The encbuckets vector only gets updated when encrypt_table is called. + +impl BridgeTable { + /// Append a new bucket to the bridge table + pub fn new_bucket(&mut self, bucket: [BridgeLine; MAX_BRIDGES_PER_BUCKET]) { + // Pick a random key to encrypt this bucket + let mut rng = rand::thread_rng(); + let mut key: [u8; 16] = [0; 16]; + rng.fill_bytes(&mut key); + self.keys.push(key); + self.buckets.push(bucket); + } + + /// Create the vector of encrypted buckets from the keys and buckets + /// 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). + pub fn encrypt_table(&mut self) { + let mut rng = rand::thread_rng(); + self.encbuckets.clear(); + for (key, bucket) in self.keys.iter().zip(self.buckets.iter()) { + let mut encbucket: [u8; ENC_BUCKET_BYTES] = [0; ENC_BUCKET_BYTES]; + let plainbucket: [u8; BUCKET_BYTES] = BridgeLine::bucket_encode(bucket); + // Set the AES key + let aeskey = GenericArray::from_slice(key); + // Pick a random nonce + let mut noncebytes: [u8; 12] = [0; 12]; + rng.fill_bytes(&mut noncebytes); + let nonce = GenericArray::from_slice(&noncebytes); + // Encrypt + let cipher = Aes128Gcm::new(aeskey); + let ciphertext: Vec = cipher.encrypt(&nonce, plainbucket.as_ref()).unwrap(); + encbucket[0..12].copy_from_slice(&noncebytes); + encbucket[12..].copy_from_slice(ciphertext.as_slice()); + self.encbuckets.push(encbucket); + } + } + + /// Decrypt an individual encrypted bucket, given its key + pub fn decrypt_bucket( + key: &[u8; 16], + encbucket: &[u8; ENC_BUCKET_BYTES], + ) -> Result<[BridgeLine; MAX_BRIDGES_PER_BUCKET], aead::Error> { + // Set the nonce and the key + let nonce = GenericArray::from_slice(&encbucket[0..12]); + let aeskey = GenericArray::from_slice(key); + // Decrypt + let cipher = Aes128Gcm::new(aeskey); + let plaintext: Vec = cipher.decrypt(&nonce, encbucket[12..].as_ref())?; + // Convert the plaintext bytes to an array of BridgeLines + Ok(BridgeLine::bucket_decode( + plaintext.as_slice().try_into().unwrap(), + )) + } +} diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index dc17633..639a231 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -17,6 +17,7 @@ The notation follows that of the paper "Hyphae: Social Secret Sharing" #[macro_use] extern crate zkp; +pub mod bridge_table; pub mod dup_filter; use sha2::Sha512; From 89b7fdf921c88f8d22a474b2497aaa1d743d8663 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Tue, 27 Apr 2021 18:26:49 -0400 Subject: [PATCH 006/115] Unit test for the bridge table --- crates/lox-library/Cargo.toml | 1 + crates/lox-library/src/bridge_table.rs | 85 +++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index 388ae60..ee389cd 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -15,6 +15,7 @@ sha2 = "0.9" lazy_static = "1" hex_fmt = "0.3" aes-gcm = "0.8" +base64 = "0.13" [features] default = ["u64_backend"] diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index 6116857..dfdc84f 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -14,7 +14,7 @@ use rand::RngCore; use std::convert::TryInto; /// Each bridge information line is serialized into this many bytes -pub const BRIDGE_BYTES: usize = 128; +pub const BRIDGE_BYTES: usize = 220; /// The max number of bridges per bucket pub const MAX_BRIDGES_PER_BUCKET: usize = 3; @@ -32,8 +32,8 @@ pub struct BridgeLine { pub addr: [u8; 16], /// port pub port: u16, - /// other protocol information, including pluggable trasport, public - /// key, etc. + /// other protocol information, including pluggable transport, + /// public key, etc. pub info: [u8; BRIDGE_BYTES - 18], } @@ -85,6 +85,40 @@ impl BridgeLine { } res } + /// Create a random BridgeLine for testing + #[cfg(test)] + pub fn random() -> Self { + let mut rng = rand::thread_rng(); + let mut res: Self = Default::default(); + // Pick a random 4-byte address + let mut addr: [u8; 4] = [0; 4]; + rng.fill_bytes(&mut addr); + // If the leading byte is 224 or more, that's not a valid IPv4 + // address. Choose an IPv6 address instead (but don't worry too + // much about it being well formed). + if addr[0] >= 224 { + rng.fill_bytes(&mut res.addr); + } else { + // Store an IPv4 address as a v4-mapped IPv6 address + res.addr[10] = 255; + res.addr[11] = 255; + res.addr[12..16].copy_from_slice(&addr); + }; + let ports: [u16; 4] = [443, 4433, 8080, 43079]; + let portidx = (rng.next_u32() % 4) as usize; + res.port = ports[portidx]; + let mut fingerprint: [u8; 20] = [0; 20]; + let mut cert: [u8; 52] = [0; 52]; + rng.fill_bytes(&mut fingerprint); + rng.fill_bytes(&mut cert); + let infostr: String = format!( + "obfs4 {} cert={} iat-mode=0", + hex_fmt::HexFmt(fingerprint), + base64::encode_config(cert, base64::STANDARD_NO_PAD) + ); + res.info[..infostr.len()].copy_from_slice(infostr.as_bytes()); + res + } } /// A BridgeTable is the internal structure holding the buckets @@ -155,3 +189,48 @@ impl BridgeTable { )) } } + +// Unit tests that require access to private fields +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_bridge_table() -> Result<(), aead::Error> { + // Create an empty bridge table + let mut btable: BridgeTable = Default::default(); + // Make 20 buckets with one random bridge each + for _ in 0..20 { + let bucket: [BridgeLine; 3] = + [BridgeLine::random(), Default::default(), Default::default()]; + btable.new_bucket(bucket); + } + // And 20 more with three random bridges each + for _ in 0..20 { + let bucket: [BridgeLine; 3] = [ + BridgeLine::random(), + BridgeLine::random(), + BridgeLine::random(), + ]; + btable.new_bucket(bucket); + } + // Create the encrypted bridge table + btable.encrypt_table(); + // Try to decrypt a 1-bridge bucket + let key7 = btable.keys[7]; + let encbucket7 = btable.encbuckets[7]; + let bucket7 = BridgeTable::decrypt_bucket(&key7, &encbucket7)?; + println!("bucket 7 = {:?}", bucket7); + // Try to decrypt a 3-bridge bucket + let key24 = btable.keys[24]; + let encbucket24 = btable.encbuckets[24]; + let bucket24 = BridgeTable::decrypt_bucket(&key24, &encbucket24)?; + println!("bucket 24 = {:?}", bucket24); + // Try to decrypt a bucket with the wrong key + let key12 = btable.keys[12]; + let encbucket15 = btable.encbuckets[15]; + let res = BridgeTable::decrypt_bucket(&key12, &encbucket15).unwrap_err(); + println!("bucket key mismatch = {:?}", res); + Ok(()) + } +} From 3ccd3087cf4fd22b945e5a077d94fdaab71b8a7a Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 28 Apr 2021 13:35:19 -0400 Subject: [PATCH 007/115] Start defining the credentials used by the system --- crates/lox-library/src/cred.rs | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 crates/lox-library/src/cred.rs diff --git a/crates/lox-library/src/cred.rs b/crates/lox-library/src/cred.rs new file mode 100644 index 0000000..97eb09d --- /dev/null +++ b/crates/lox-library/src/cred.rs @@ -0,0 +1,40 @@ +/*! The various credentials used by the system. 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). */ + +use curve25519_dalek::ristretto::RistrettoPoint; +use curve25519_dalek::scalar::Scalar; + +/// 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. +pub struct Migration { + pub P: RistrettoPoint, + pub Q: RistrettoPoint, + pub lox_id: Scalar, + pub from_bucket: Scalar, + pub to_bucket: Scalar, +} + +/// 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 Julian date of when this +/// user was changed to the current trust level. (P_noopmigration, +/// Q_noopmigration) are the MAC on the implicit no-op migration +/// credential formed by the attributes (id, bucket, bucket), which +/// authorizes the user to switch from its current bucket to the same +/// bucket (i.e., a no-op). This can be useful for hiding from the BA +/// whether or not the user is performing a bucket migration. +pub struct Lox { + pub P: RistrettoPoint, + pub Q: RistrettoPoint, + pub id: Scalar, + pub bucket: Scalar, + pub trust_level: Scalar, + pub level_since: Scalar, + pub invites_remaining: Scalar, + pub invites_issued: Scalar, + pub P_noopmigration: RistrettoPoint, + pub Q_noopmigration: RistrettoPoint, +} From 996463d1c02a48d79bd994de5f79b637064185c6 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 28 Apr 2021 13:36:04 -0400 Subject: [PATCH 008/115] Start creating the bridge authority --- crates/lox-library/Cargo.toml | 1 + crates/lox-library/src/lib.rs | 64 ++++++++++++++++++++++++++++++- crates/lox-library/tests/tests.rs | 9 +++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index ee389cd..248d432 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -16,6 +16,7 @@ lazy_static = "1" hex_fmt = "0.3" aes-gcm = "0.8" base64 = "0.13" +time = "0.2" [features] default = ["u64_backend"] diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 639a231..109ac54 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -18,6 +18,7 @@ The notation follows that of the paper "Hyphae: Social Secret Sharing" extern crate zkp; pub mod bridge_table; +pub mod cred; pub mod dup_filter; use sha2::Sha512; @@ -114,11 +115,11 @@ pub const OPENINV_LENGTH: usize = 32 // the length of the random impl BridgeDb { /// Create the BridgeDb. - pub fn new(num_openinv_buckets: u32) -> BridgeDb { + pub fn new(num_openinv_buckets: u32) -> Self { let mut csprng = OsRng {}; let keypair = Keypair::generate(&mut csprng); let pubkey = keypair.public; - BridgeDb { + Self { keypair, pubkey, num_openinv_buckets, @@ -165,3 +166,62 @@ impl BridgeDb { } } } + +/// The bridge authority. This will typically be a singleton object. +#[derive(Debug)] +pub struct BridgeAuth { + /// The private key for the main Lox credential + lox_priv: IssuerPrivKey, + /// The public key for the main Lox credential + pub lox_pub: IssuerPubKey, + /// The private key for migration credentials + migration_priv: IssuerPrivKey, + /// The public key for migration credentials + pub migration_pub: IssuerPubKey, + + /// The public key of the BridgeDb issuing open invitations + pub bridgedb_pub: PublicKey, + + /// Duplicate filter for open invitations + openinv_filter: dup_filter::DupFilter, + /// Duplicate filter for credential ids + id_filter: dup_filter::DupFilter, + + /// For testing only: offset of the true time to the simulated time + time_offset: time::Duration, +} + +impl BridgeAuth { + pub fn new(bridgedb_pub: PublicKey) -> Self { + let lox_priv = IssuerPrivKey::new(6); + let lox_pub = IssuerPubKey::new(&lox_priv); + let migration_priv = IssuerPrivKey::new(3); + let migration_pub = IssuerPubKey::new(&migration_priv); + Self { + lox_priv, + lox_pub, + migration_priv, + migration_pub, + bridgedb_pub, + openinv_filter: Default::default(), + id_filter: Default::default(), + time_offset: time::Duration::zero(), + } + } + + /// For testing only: manually advance the day by 1 day + pub fn advance_day(&mut self) { + self.time_offset += time::Duration::days(1); + } + + /// 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 + fn today(&self) -> i64 { + (time::OffsetDateTime::now_utc().date() + self.time_offset).julian_day() + } +} diff --git a/crates/lox-library/tests/tests.rs b/crates/lox-library/tests/tests.rs index ce497fa..9c67e68 100644 --- a/crates/lox-library/tests/tests.rs +++ b/crates/lox-library/tests/tests.rs @@ -1,5 +1,6 @@ use lox::dup_filter; use lox::dup_filter::SeenType::{Fresh, Seen}; +use lox::BridgeAuth; use lox::BridgeDb; use curve25519_dalek::scalar::Scalar; @@ -44,3 +45,11 @@ fn test_dup_filter() { println!("df1 = {:?}", df1); println!("df2 = {:?}", df2); } + +#[test] +fn test_bridgeauth() { + let bdb = BridgeDb::new(20); + let mut ba = BridgeAuth::new(bdb.pubkey); + ba.advance_day(); + ba.advance_days(30); +} From 706f4846068ba72e7d227ce4a3a959a85fb78b7e Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 28 Apr 2021 15:42:16 -0400 Subject: [PATCH 009/115] The request message of the open invitation protocol --- crates/lox-library/src/lib.rs | 2 + crates/lox-library/src/open_invite.rs | 116 ++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 crates/lox-library/src/open_invite.rs diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 109ac54..b6fd8c5 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -225,3 +225,5 @@ impl BridgeAuth { (time::OffsetDateTime::now_utc().date() + self.time_offset).julian_day() } } + +pub mod open_invite; diff --git a/crates/lox-library/src/open_invite.rs b/crates/lox-library/src/open_invite.rs new file mode 100644 index 0000000..01a81d7 --- /dev/null +++ b/crates/lox-library/src/open_invite.rs @@ -0,0 +1,116 @@ +/*! A module for the protocol for the user to redeem an open invitation +with the BA (bridge authority) to receive their initial Lox +credential. The credential will have attributes: + +- id: jointly chosen by the user and BA +- bucket: set by the BA +- trust_level: 0 +- level_since: today +- invites_remaining: 0 +- invites_issued: 0 + +*/ + +use curve25519_dalek::ristretto::RistrettoBasepointTable; +use curve25519_dalek::ristretto::RistrettoPoint; +use curve25519_dalek::scalar::Scalar; +use curve25519_dalek::traits::IsIdentity; + +use zkp::CompactProof; +use zkp::ProofError; +use zkp::Transcript; + +use super::{BridgeAuth, IssuerPubKey}; +use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; + +/// The request message for this protocol +pub struct Request { + invite: [u8; super::OPENINV_LENGTH], + D: RistrettoPoint, + EncIdClient: (RistrettoPoint, RistrettoPoint), + piUserBlinding: CompactProof, +} + +#[derive(Debug)] +/// The client state for this protocol +pub struct State { + d: Scalar, + D: RistrettoPoint, + EncIdClient: (RistrettoPoint, RistrettoPoint), + id_client: Scalar, +} + +/// The response message for this protocol +pub struct Response { + P: RistrettoPoint, + EncQ: (RistrettoPoint, RistrettoPoint), + id_server: Scalar, + TId: RistrettoPoint, + bucket: Scalar, + level_since: Scalar, + P_noopmigration: RistrettoPoint, + EncQ_noopmigration: (RistrettoPoint, RistrettoPoint), + TId_noopmigration: RistrettoPoint, +} + +// The userblinding ZKP +define_proof! { + userblinding, + "Open Invitation User Blinding", + (d, eid_client, id_client), + (EncIdClient0, EncIdClient1, D), + (B) : + EncIdClient0 = (eid_client*B), + EncIdClient1 = (id_client*B + eid_client*D), + D = (d*B) +} + +/// Submit an open invitation issued by the BridgeDb to receive your +/// first Lox credential +pub fn request(invite: &[u8; super::OPENINV_LENGTH]) -> (Request, State) { + let B: &RistrettoPoint = &CMZ_B; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + // Pick an ElGamal keypair + let mut rng = rand::thread_rng(); + let d = Scalar::random(&mut rng); + let D = &d * Btable; + + // Pick a random client component of the id + let id_client = Scalar::random(&mut rng); + + // Encrypt it (times the basepoint B) to the ElGamal public key D we + // just created + let eid_client = Scalar::random(&mut rng); + let EncIdClient = (&eid_client * Btable, &id_client * Btable + eid_client * D); + + // Construct the proof of correct user blinding + let mut transcript = Transcript::new(b"open invite user blinding"); + let piUserBlinding = userblinding::prove_compact( + &mut transcript, + userblinding::ProveAssignments { + B: &B, + EncIdClient0: &EncIdClient.0, + EncIdClient1: &EncIdClient.1, + D: &D, + d: &d, + eid_client: &eid_client, + id_client: &id_client, + }, + ) + .0; + ( + Request { + invite: *invite, + D, + EncIdClient, + piUserBlinding, + }, + State { + d, + D, + EncIdClient, + id_client, + }, + ) +} From e9267f5b373e3e3dd5f93e6263b93b826851b6a9 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 28 Apr 2021 18:31:47 -0400 Subject: [PATCH 010/115] The response message of the open invitation protocol --- crates/lox-library/src/bridge_table.rs | 26 +++- crates/lox-library/src/lib.rs | 13 +- crates/lox-library/src/open_invite.rs | 200 ++++++++++++++++++++++++- 3 files changed, 232 insertions(+), 7 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index dfdc84f..8429f52 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -10,6 +10,7 @@ use aes_gcm::aead; use aes_gcm::aead::{generic_array::GenericArray, Aead, NewAead}; use aes_gcm::Aes128Gcm; +use curve25519_dalek::scalar::Scalar; use rand::RngCore; use std::convert::TryInto; @@ -128,15 +129,20 @@ impl BridgeLine { /// decryption key for one bucket. #[derive(Debug, Default)] pub struct BridgeTable { - keys: Vec<[u8; 16]>, - buckets: Vec<[BridgeLine; MAX_BRIDGES_PER_BUCKET]>, - encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>, + pub keys: Vec<[u8; 16]>, + pub buckets: Vec<[BridgeLine; MAX_BRIDGES_PER_BUCKET]>, + pub encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>, } // Invariant: the lengths of the keys and buckets vectors are the same. // The encbuckets vector only gets updated when encrypt_table is called. impl BridgeTable { + /// Get the number of buckets in the bridge table + pub fn num_buckets(&self) -> usize { + self.buckets.len() + } + /// Append a new bucket to the bridge table pub fn new_bucket(&mut self, bucket: [BridgeLine; MAX_BRIDGES_PER_BUCKET]) { // Pick a random key to encrypt this bucket @@ -190,7 +196,8 @@ impl BridgeTable { } } -// Unit tests that require access to private fields +// Unit tests that require access to the testing-only function +// BridgeLine::random() #[cfg(test)] mod tests { use super::*; @@ -234,3 +241,14 @@ mod tests { Ok(()) } } + +/// Convert an id and key to a Scalar attribute +pub fn to_scalar(id: u32, key: [u8; 16]) -> Scalar { + let mut b: [u8; 32] = [0; 32]; + // b is a little-endian representation of the Scalar; put the key in + // the low 16 bytes, and the id in the next 4 bytes. + b[0..16].copy_from_slice(&key); + b[16..20].copy_from_slice(&id.to_le_bytes()); + // This cannot fail, since we're only using the low 20 bytes of b + Scalar::from_canonical_bytes(b).unwrap() +} diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index b6fd8c5..1e1b1e6 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -182,6 +182,9 @@ pub struct BridgeAuth { /// The public key of the BridgeDb issuing open invitations pub bridgedb_pub: PublicKey, + /// The bridge table + bridge_table: bridge_table::BridgeTable, + /// Duplicate filter for open invitations openinv_filter: dup_filter::DupFilter, /// Duplicate filter for credential ids @@ -203,6 +206,7 @@ impl BridgeAuth { migration_priv, migration_pub, bridgedb_pub, + bridge_table: Default::default(), openinv_filter: Default::default(), id_filter: Default::default(), time_offset: time::Duration::zero(), @@ -221,9 +225,14 @@ impl BridgeAuth { } /// Get today's (real or simulated) date - fn today(&self) -> i64 { - (time::OffsetDateTime::now_utc().date() + self.time_offset).julian_day() + fn today(&self) -> u64 { + // We will not encounter negative Julian dates (~6700 years ago) + (time::OffsetDateTime::now_utc().date() + self.time_offset) + .julian_day() + .try_into() + .unwrap() } } +// The protocol modules pub mod open_invite; diff --git a/crates/lox-library/src/open_invite.rs b/crates/lox-library/src/open_invite.rs index 01a81d7..128f2b3 100644 --- a/crates/lox-library/src/open_invite.rs +++ b/crates/lox-library/src/open_invite.rs @@ -14,12 +14,13 @@ credential. The credential will have attributes: use curve25519_dalek::ristretto::RistrettoBasepointTable; use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; -use curve25519_dalek::traits::IsIdentity; use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; +use super::bridge_table; +use super::dup_filter::SeenType; use super::{BridgeAuth, IssuerPubKey}; use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; @@ -51,6 +52,7 @@ pub struct Response { P_noopmigration: RistrettoPoint, EncQ_noopmigration: (RistrettoPoint, RistrettoPoint), TId_noopmigration: RistrettoPoint, + piBlindIssue: CompactProof, } // The userblinding ZKP @@ -65,6 +67,36 @@ define_proof! { D = (d*B) } +// The issuing ZKP +define_proof! { + blindissue, + "Open Invitation Blind Issuing", + (x0, x0tilde, xid, xbucket, xsince, s, b, tid, + x0_nm, x0tilde_nm, xid_nm, xfrom_nm, xto_nm, s_nm, b_nm, tid_nm), + (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xsince, Pbucket, Psince, TId, + P_nm, EncQ0_nm, EncQ1_nm, X0_nm, Xid_nm, Xfrom_nm, Xto_nm, TId_nm, + D, EncId0, EncId1), + (A, B) : + Xid = (xid*A), + Xbucket = (xbucket*A), + Xsince = (xsince*A), + X0 = (x0*B + x0tilde*A), + P = (b*B), + TId = (b*Xid), + TId = (tid*A), + EncQ0 = (s*B + tid*EncId0), + EncQ1 = (s*D + tid*EncId1 + x0*P + xbucket*Pbucket + xsince*Psince), + Xid_nm = (xid_nm*A), + Xfrom_nm = (xfrom_nm*A), + Xto_nm = (xto_nm*A), + X0_nm = (x0_nm*B + x0tilde_nm*A), + P_nm = (b_nm*B), + TId_nm = (b_nm*Xid_nm), + TId_nm = (tid_nm*A), + EncQ0_nm = (s_nm*B + tid_nm*EncId0), + EncQ1_nm = (s_nm*D + tid_nm*EncId1 + x0_nm*P_nm + xfrom_nm*Pbucket + xto_nm*Pbucket) +} + /// Submit an open invitation issued by the BridgeDb to receive your /// first Lox credential pub fn request(invite: &[u8; super::OPENINV_LENGTH]) -> (Request, State) { @@ -114,3 +146,169 @@ pub fn request(invite: &[u8; super::OPENINV_LENGTH]) -> (Request, State) { }, ) } + +impl BridgeAuth { + /// Receive an open invitation issued by the BridgeDb and if it is + /// valid and fresh, issue a Lox credential at trust level 0. + pub fn handle_open_invite(&mut self, req: Request) -> Result { + // Check the signature on the open_invite. We manually match + // here because we're changing the Err type from SignatureError + // to ProofError + let (invite_id, bucket_id_u32) = + match super::BridgeDb::verify(req.invite, self.bridgedb_pub) { + Ok(res) => res, + Err(_) => return Err(ProofError::VerificationFailure), + }; + let bucket_id: usize = bucket_id_u32 as usize; + + // Only proceed if the invite_id is fresh + if self.openinv_filter.filter(&invite_id) == SeenType::Seen { + return Err(ProofError::VerificationFailure); + } + + // And also check that the bucket id is valid + if bucket_id >= self.bridge_table.num_buckets() { + return Err(ProofError::VerificationFailure); + } + + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + // Next check the proof in the request + let mut transcript = Transcript::new(b"open invite user blinding"); + userblinding::verify_compact( + &req.piUserBlinding, + &mut transcript, + userblinding::VerifyAssignments { + B: &B.compress(), + EncIdClient0: &req.EncIdClient.0.compress(), + EncIdClient1: &req.EncIdClient.1.compress(), + D: &req.D.compress(), + }, + )?; + + // Choose a random server id component to add to the client's + // (blinded) id component + let mut rng = rand::thread_rng(); + let id_server = Scalar::random(&mut rng); + let EncId = (req.EncIdClient.0, req.EncIdClient.1 + &id_server * Btable); + + // Create the bucket attribute (Scalar), which is a combination + // of the bucket id (u32) and the bucket's decryption key ([u8; 16]) + let bucket_key = self.bridge_table.keys[bucket_id]; + let bucket: Scalar = bridge_table::to_scalar(bucket_id_u32, bucket_key); + + // Create the level_since attribute (Scalar), which is today's + // Julian date + let level_since: Scalar = self.today().into(); + + // Compute the MAC on the visible attributes + let b = Scalar::random(&mut rng); + let P = &b * Btable; + // trust_level = invites_remaining = invites_issued = 0 + let QHc = + (self.lox_priv.x[0] + self.lox_priv.x[2] * bucket + self.lox_priv.x[4] * level_since) + * P; + + // El Gamal encrypt it to the public key req.D + let s = Scalar::random(&mut rng); + let EncQHc = (&s * Btable, QHc + s * req.D); + + // Homomorphically compute the part of the MAC corresponding to + // the blinded id attribute + let tid = self.lox_priv.x[1] * b; + let TId = &tid * Atable; + let EncQId = (tid * EncId.0, tid * EncId.1); + + let EncQ = (EncQHc.0 + EncQId.0, EncQHc.1 + EncQId.1); + + // Now the no-op migration credential + // Compute the MAC on the visible attributes + let b_noopmigration = Scalar::random(&mut rng); + let P_noopmigration = &b_noopmigration * Btable; + let QHc_noopmigration = (self.migration_priv.x[0] + + self.migration_priv.x[2] * bucket + + self.migration_priv.x[3] * bucket) + * P; + + // El Gamal encrypt it to the public key req.D + let s_noopmigration = Scalar::random(&mut rng); + let EncQHc_noopmigration = ( + &s_noopmigration * Btable, + QHc_noopmigration + s_noopmigration * req.D, + ); + + // Homomorphically compute the part of the MAC corresponding to + // the blinded id attribute + let tid_noopmigration = self.migration_priv.x[1] * b_noopmigration; + let TId_noopmigration = &tid_noopmigration * Atable; + let EncQId_noopmigration = (tid_noopmigration * EncId.0, tid_noopmigration * EncId.1); + + let EncQ_noopmigration = ( + EncQHc_noopmigration.0 + EncQId_noopmigration.0, + EncQHc_noopmigration.1 + EncQId_noopmigration.1, + ); + + let mut transcript = Transcript::new(b"open invite issuing"); + let piBlindIssue = blindissue::prove_compact( + &mut transcript, + blindissue::ProveAssignments { + A: &A, + B: &B, + P: &P, + EncQ0: &EncQ.0, + EncQ1: &EncQ.1, + X0: &self.lox_pub.X[0], + Xid: &self.lox_pub.X[1], + Xbucket: &self.lox_pub.X[2], + Xsince: &self.lox_pub.X[4], + Pbucket: &(bucket * P), + Psince: &(level_since * P), + TId: &TId, + P_nm: &P_noopmigration, + EncQ0_nm: &EncQ_noopmigration.0, + EncQ1_nm: &EncQ_noopmigration.1, + X0_nm: &self.migration_pub.X[0], + Xid_nm: &self.migration_pub.X[1], + Xfrom_nm: &self.migration_pub.X[2], + Xto_nm: &self.migration_pub.X[3], + TId_nm: &TId_noopmigration, + D: &req.D, + EncId0: &EncId.0, + EncId1: &EncId.1, + x0: &self.lox_priv.x[0], + x0tilde: &self.lox_priv.x0tilde, + xid: &self.lox_priv.x[1], + xbucket: &self.lox_priv.x[2], + xsince: &self.lox_priv.x[4], + s: &s, + b: &b, + tid: &tid, + x0_nm: &self.migration_priv.x[0], + x0tilde_nm: &self.migration_priv.x0tilde, + xid_nm: &self.migration_priv.x[1], + xfrom_nm: &self.migration_priv.x[2], + xto_nm: &self.migration_priv.x[3], + s_nm: &s_noopmigration, + b_nm: &b_noopmigration, + tid_nm: &tid_noopmigration, + }, + ) + .0; + + Ok(Response { + P, + EncQ, + id_server, + TId, + bucket, + level_since, + P_noopmigration, + EncQ_noopmigration, + TId_noopmigration, + piBlindIssue, + }) + } +} From 75630d3ad0b8e05867c4f32adf1464d2925644b6 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 28 Apr 2021 18:48:52 -0400 Subject: [PATCH 011/115] Unit test for what's done of the open invite protocol so far --- crates/lox-library/src/lib.rs | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 1e1b1e6..88d1fb2 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -236,3 +236,44 @@ impl BridgeAuth { // The protocol modules pub mod open_invite; + +// Unit tests that require access to the testing-only function +// BridgeLine::random() +#[cfg(test)] +mod tests { + use super::bridge_table::BridgeLine; + use super::*; + + #[test] + fn test_open_invite() { + // Create a BridegDb + let bdb = BridgeDb::new(20); + // Create a BridgeAuth + let mut ba = BridgeAuth::new(bdb.pubkey); + + // Make 20 buckets with one random bridge each + for _ in 0..20 { + let bucket: [BridgeLine; 3] = + [BridgeLine::random(), Default::default(), Default::default()]; + ba.bridge_table.new_bucket(bucket); + } + // And 20 more with three random bridges each + for _ in 0..20 { + let bucket: [BridgeLine; 3] = [ + BridgeLine::random(), + BridgeLine::random(), + BridgeLine::random(), + ]; + ba.bridge_table.new_bucket(bucket); + } + // Create the encrypted bridge table + ba.bridge_table.encrypt_table(); + + // Issue an open invitation + let inv = bdb.invite(); + + // Use it to get a Lox credential + let (req, state) = open_invite::request(&inv); + let resp = ba.handle_open_invite(req); + } +} From 2791f0bf54e88f23f782514799284363c7195764 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 28 Apr 2021 23:02:45 -0400 Subject: [PATCH 012/115] Handle the response of the open invitation protocol to produce the Lox credential --- crates/lox-library/src/cred.rs | 2 + crates/lox-library/src/lib.rs | 5 +- crates/lox-library/src/open_invite.rs | 87 ++++++++++++++++++++++++++- 3 files changed, 90 insertions(+), 4 deletions(-) diff --git a/crates/lox-library/src/cred.rs b/crates/lox-library/src/cred.rs index 97eb09d..46a6ab9 100644 --- a/crates/lox-library/src/cred.rs +++ b/crates/lox-library/src/cred.rs @@ -9,6 +9,7 @@ use curve25519_dalek::scalar::Scalar; /// 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. +#[derive(Debug)] pub struct Migration { pub P: RistrettoPoint, pub Q: RistrettoPoint, @@ -26,6 +27,7 @@ pub struct Migration { /// authorizes the user to switch from its current bucket to the same /// bucket (i.e., a no-op). This can be useful for hiding from the BA /// whether or not the user is performing a bucket migration. +#[derive(Debug)] pub struct Lox { pub P: RistrettoPoint, pub Q: RistrettoPoint, diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 88d1fb2..a81bcee 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -274,6 +274,9 @@ mod tests { // Use it to get a Lox credential let (req, state) = open_invite::request(&inv); - let resp = ba.handle_open_invite(req); + let resp = ba.handle_open_invite(req).unwrap(); + let cred = + open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); + println!("cred = {:?}", cred); } } diff --git a/crates/lox-library/src/open_invite.rs b/crates/lox-library/src/open_invite.rs index 128f2b3..d55e077 100644 --- a/crates/lox-library/src/open_invite.rs +++ b/crates/lox-library/src/open_invite.rs @@ -14,12 +14,14 @@ credential. The credential will have attributes: use curve25519_dalek::ristretto::RistrettoBasepointTable; use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; +use curve25519_dalek::traits::IsIdentity; use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; use super::bridge_table; +use super::cred; use super::dup_filter::SeenType; use super::{BridgeAuth, IssuerPubKey}; use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; @@ -74,7 +76,8 @@ define_proof! { (x0, x0tilde, xid, xbucket, xsince, s, b, tid, x0_nm, x0tilde_nm, xid_nm, xfrom_nm, xto_nm, s_nm, b_nm, tid_nm), (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xsince, Pbucket, Psince, TId, - P_nm, EncQ0_nm, EncQ1_nm, X0_nm, Xid_nm, Xfrom_nm, Xto_nm, TId_nm, + P_nm, EncQ0_nm, EncQ1_nm, X0_nm, Xid_nm, Xfrom_nm, Xto_nm, + Pbucket_nm, TId_nm, D, EncId0, EncId1), (A, B) : Xid = (xid*A), @@ -94,7 +97,7 @@ define_proof! { TId_nm = (b_nm*Xid_nm), TId_nm = (tid_nm*A), EncQ0_nm = (s_nm*B + tid_nm*EncId0), - EncQ1_nm = (s_nm*D + tid_nm*EncId1 + x0_nm*P_nm + xfrom_nm*Pbucket + xto_nm*Pbucket) + EncQ1_nm = (s_nm*D + tid_nm*EncId1 + x0_nm*P_nm + xfrom_nm*Pbucket_nm + xto_nm*Pbucket_nm) } /// Submit an open invitation issued by the BridgeDb to receive your @@ -231,7 +234,7 @@ impl BridgeAuth { let QHc_noopmigration = (self.migration_priv.x[0] + self.migration_priv.x[2] * bucket + self.migration_priv.x[3] * bucket) - * P; + * P_noopmigration; // El Gamal encrypt it to the public key req.D let s_noopmigration = Scalar::random(&mut rng); @@ -274,6 +277,7 @@ impl BridgeAuth { Xid_nm: &self.migration_pub.X[1], Xfrom_nm: &self.migration_pub.X[2], Xto_nm: &self.migration_pub.X[3], + Pbucket_nm: &(bucket * P_noopmigration), TId_nm: &TId_noopmigration, D: &req.D, EncId0: &EncId.0, @@ -312,3 +316,80 @@ impl BridgeAuth { }) } } + +/// Handle the reponse to the request, producing the desired Lox +/// credential if successful. +pub fn handle_response( + state: State, + resp: Response, + lox_pub: &IssuerPubKey, + migration_pub: &IssuerPubKey, +) -> Result { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + if resp.P.is_identity() || resp.P_noopmigration.is_identity() { + return Err(ProofError::VerificationFailure); + } + + // Add the server's contribution to the id to our own, both in plain + // and encrypted form + let id = state.id_client + resp.id_server; + let EncId = ( + state.EncIdClient.0, + state.EncIdClient.1 + &resp.id_server * Btable, + ); + + // Verify the proof + let mut transcript = Transcript::new(b"open invite issuing"); + blindissue::verify_compact( + &resp.piBlindIssue, + &mut transcript, + blindissue::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P: &resp.P.compress(), + EncQ0: &resp.EncQ.0.compress(), + EncQ1: &resp.EncQ.1.compress(), + X0: &lox_pub.X[0].compress(), + Xid: &lox_pub.X[1].compress(), + Xbucket: &lox_pub.X[2].compress(), + Xsince: &lox_pub.X[4].compress(), + Pbucket: &(resp.bucket * resp.P).compress(), + Psince: &(resp.level_since * resp.P).compress(), + TId: &resp.TId.compress(), + P_nm: &resp.P_noopmigration.compress(), + EncQ0_nm: &resp.EncQ_noopmigration.0.compress(), + EncQ1_nm: &resp.EncQ_noopmigration.1.compress(), + X0_nm: &migration_pub.X[0].compress(), + Xid_nm: &migration_pub.X[1].compress(), + Xfrom_nm: &migration_pub.X[2].compress(), + Xto_nm: &migration_pub.X[3].compress(), + Pbucket_nm: &(resp.bucket * resp.P_noopmigration).compress(), + TId_nm: &resp.TId_noopmigration.compress(), + D: &state.D.compress(), + EncId0: &EncId.0.compress(), + EncId1: &EncId.1.compress(), + }, + )?; + + // Decrypt EncQ + let Q = resp.EncQ.1 - (state.d * resp.EncQ.0); + + // Decrypt EncQ_noopmigration + let Q_noopmigration = resp.EncQ_noopmigration.1 - (state.d * resp.EncQ_noopmigration.0); + + Ok(cred::Lox { + P: resp.P, + Q, + id, + bucket: resp.bucket, + trust_level: Scalar::zero(), + level_since: resp.level_since, + invites_remaining: Scalar::zero(), + invites_issued: Scalar::zero(), + P_noopmigration: resp.P_noopmigration, + Q_noopmigration, + }) +} From 77b92036c757cc94ca3da1714e87dc52ac92a2af Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 28 Apr 2021 23:12:50 -0400 Subject: [PATCH 013/115] Update the name of one test --- crates/lox-library/tests/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lox-library/tests/tests.rs b/crates/lox-library/tests/tests.rs index 9c67e68..bc2c799 100644 --- a/crates/lox-library/tests/tests.rs +++ b/crates/lox-library/tests/tests.rs @@ -6,7 +6,7 @@ use lox::BridgeDb; use curve25519_dalek::scalar::Scalar; #[test] -fn test_openinvite() { +fn test_bridgedb() { let bdb = BridgeDb::new(20); let inv = bdb.invite(); println!("{:?}", inv); From 450c62bfc7b1ef09c80817dd192ac059c68cbbbd Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Thu, 29 Apr 2021 11:28:05 -0400 Subject: [PATCH 014/115] Check that we can use the credential to read a bucket --- crates/lox-library/Cargo.toml | 1 + crates/lox-library/src/bridge_table.rs | 33 +++++++++++++++++++++----- crates/lox-library/src/lib.rs | 5 ++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index 248d432..9a2ffcb 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -17,6 +17,7 @@ hex_fmt = "0.3" aes-gcm = "0.8" base64 = "0.13" time = "0.2" +subtle = "2.4" [features] default = ["u64_backend"] diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index 8429f52..550d278 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -13,6 +13,7 @@ use aes_gcm::Aes128Gcm; use curve25519_dalek::scalar::Scalar; use rand::RngCore; use std::convert::TryInto; +use subtle::ConstantTimeEq; /// Each bridge information line is serialized into this many bytes pub const BRIDGE_BYTES: usize = 220; @@ -194,6 +195,16 @@ impl BridgeTable { plaintext.as_slice().try_into().unwrap(), )) } + + /// Decrypt an individual encrypted bucket, given its id and key + pub fn decrypt_bucket_id( + &self, + id: u32, + key: &[u8; 16], + ) -> Result<[BridgeLine; MAX_BRIDGES_PER_BUCKET], aead::Error> { + let encbucket = self.encbuckets[id as usize]; + BridgeTable::decrypt_bucket(key, &encbucket) + } } // Unit tests that require access to the testing-only function @@ -225,18 +236,15 @@ mod tests { btable.encrypt_table(); // Try to decrypt a 1-bridge bucket let key7 = btable.keys[7]; - let encbucket7 = btable.encbuckets[7]; - let bucket7 = BridgeTable::decrypt_bucket(&key7, &encbucket7)?; + let bucket7 = btable.decrypt_bucket_id(7, &key7)?; println!("bucket 7 = {:?}", bucket7); // Try to decrypt a 3-bridge bucket let key24 = btable.keys[24]; - let encbucket24 = btable.encbuckets[24]; - let bucket24 = BridgeTable::decrypt_bucket(&key24, &encbucket24)?; + let bucket24 = btable.decrypt_bucket_id(24, &key24)?; println!("bucket 24 = {:?}", bucket24); // Try to decrypt a bucket with the wrong key let key12 = btable.keys[12]; - let encbucket15 = btable.encbuckets[15]; - let res = BridgeTable::decrypt_bucket(&key12, &encbucket15).unwrap_err(); + let res = btable.decrypt_bucket_id(15, &key12).unwrap_err(); println!("bucket key mismatch = {:?}", res); Ok(()) } @@ -252,3 +260,16 @@ pub fn to_scalar(id: u32, key: [u8; 16]) -> Scalar { // This cannot fail, since we're only using the low 20 bytes of b Scalar::from_canonical_bytes(b).unwrap() } + +/// Convert a Scalar attribute to an id and key if possible +pub fn from_scalar(s: Scalar) -> Result<(u32, [u8; 16]), aead::Error> { + // Check that the top 12 bytes of the Scalar are 0 + let sbytes = s.as_bytes(); + if sbytes[20..].ct_eq(&[0u8; 12]).unwrap_u8() == 0 { + return Err(aead::Error); + } + let id = u32::from_le_bytes(sbytes[16..20].try_into().unwrap()); + let mut key: [u8; 16] = [0; 16]; + key.copy_from_slice(&sbytes[..16]); + Ok((id, key)) +} diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index a81bcee..1972ea2 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -277,6 +277,11 @@ mod tests { let resp = ba.handle_open_invite(req).unwrap(); let cred = open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); + + // Check that we can use the credential to read a bucket + let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); + let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap(); println!("cred = {:?}", cred); + println!("bucket = {:?}", bucket); } } From b86973174a4c1d772d9f18d3f2860588bc6866de Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Thu, 29 Apr 2021 14:58:51 -0400 Subject: [PATCH 015/115] Fix up formatting of module doc comments --- crates/lox-library/src/bridge_table.rs | 17 +++++++++-------- crates/lox-library/src/cred.rs | 9 +++++---- crates/lox-library/src/dup_filter.rs | 7 ++++--- crates/lox-library/src/open_invite.rs | 4 +++- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index 550d278..65e7ac8 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -1,11 +1,12 @@ -/*! The encrypted table of bridges. The table consists of a number of - * buckets, each holding some number (currently up to 3) of bridges. - * Each bucket is individually encrypted with a bucket key. Users will - * have a credential containing a bucket (number, key) combination, and - * so will be able to read one of the buckets. Users will either - * download the whole encrypted bucket list or use PIR to download a - * piece of it, so that the bridge authority does not learn which bucket - * the user has access to. */ +/*! The encrypted table of bridges. + +The table consists of a number of buckets, each holding some number +(currently up to 3) of bridges. Each bucket is individually encrypted +with a bucket key. Users will have a credential containing a bucket +(number, key) combination, and so will be able to read one of the +buckets. Users will either download the whole encrypted bucket list or +use PIR to download a piece of it, so that the bridge authority does not +learn which bucket the user has access to. */ use aes_gcm::aead; use aes_gcm::aead::{generic_array::GenericArray, Aead, NewAead}; diff --git a/crates/lox-library/src/cred.rs b/crates/lox-library/src/cred.rs index 46a6ab9..241b03f 100644 --- a/crates/lox-library/src/cred.rs +++ b/crates/lox-library/src/cred.rs @@ -1,7 +1,8 @@ -/*! The various credentials used by the system. 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). */ +/*! The various credentials used by the system. + +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). */ use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; diff --git a/crates/lox-library/src/dup_filter.rs b/crates/lox-library/src/dup_filter.rs index b128261..3a2a797 100644 --- a/crates/lox-library/src/dup_filter.rs +++ b/crates/lox-library/src/dup_filter.rs @@ -1,7 +1,8 @@ /*! Filter duplicate shows of credentials and open invitations by id - * (which will typically be a Scalar). This implementation just keeps - * the table of seen ids in memory, but a production one would of course - * use a disk-backed database. */ +(which will typically be a Scalar). + +This implementation just keeps the table of seen ids in memory, but a +production one would of course use a disk-backed database. */ use std::cmp::Eq; use std::collections::HashMap; diff --git a/crates/lox-library/src/open_invite.rs b/crates/lox-library/src/open_invite.rs index d55e077..cef5dcd 100644 --- a/crates/lox-library/src/open_invite.rs +++ b/crates/lox-library/src/open_invite.rs @@ -1,6 +1,8 @@ /*! A module for the protocol for the user to redeem an open invitation with the BA (bridge authority) to receive their initial Lox -credential. The credential will have attributes: +credential. + +The credential will have attributes: - id: jointly chosen by the user and BA - bucket: set by the BA From e7bb50ab2ba781d37e5977d33c18e6a0a9827c9b Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Thu, 29 Apr 2021 15:18:54 -0400 Subject: [PATCH 016/115] Start on trust promotion This is the protocol for the user to get promoted from untrusted (trust level 0) to trusted (trust level 1). --- crates/lox-library/src/bridge_table.rs | 2 +- crates/lox-library/src/cred.rs | 16 ++++++ crates/lox-library/src/lib.rs | 64 +++++++++++++++++++++++ crates/lox-library/src/migration_table.rs | 15 ++++++ crates/lox-library/src/trust_promotion.rs | 50 ++++++++++++++++++ 5 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 crates/lox-library/src/migration_table.rs create mode 100644 crates/lox-library/src/trust_promotion.rs diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index 65e7ac8..3abc640 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -29,7 +29,7 @@ pub const BUCKET_BYTES: usize = BRIDGE_BYTES * MAX_BRIDGES_PER_BUCKET; pub const ENC_BUCKET_BYTES: usize = BUCKET_BYTES + 12 + 16; /// A bridge information line -#[derive(Debug)] +#[derive(Copy, Clone, Debug)] pub struct BridgeLine { /// IPv4 or IPv6 address pub addr: [u8; 16], diff --git a/crates/lox-library/src/cred.rs b/crates/lox-library/src/cred.rs index 241b03f..871f6c6 100644 --- a/crates/lox-library/src/cred.rs +++ b/crates/lox-library/src/cred.rs @@ -41,3 +41,19 @@ pub struct Lox { pub P_noopmigration: RistrettoPoint, pub Q_noopmigration: RistrettoPoint, } + +// The migration key credential is never actually instantiated. It is +// an implicit credential with the following attributes: +// - lox_id: Scalar, +// - from_bucket: Scalar +// Plus the usual (P,Q) MAC. 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 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 credential +// with their new bucket, without the BA learning either their old or +// new buckets. diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 1972ea2..52159df 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -20,6 +20,8 @@ extern crate zkp; pub mod bridge_table; pub mod cred; pub mod dup_filter; +pub mod migration_table; +pub mod trust_promotion; use sha2::Sha512; @@ -178,6 +180,10 @@ pub struct BridgeAuth { migration_priv: IssuerPrivKey, /// The public key for migration credentials pub migration_pub: IssuerPubKey, + /// The private key for migration key credentials + migrationkey_priv: IssuerPrivKey, + /// The public key for migration key credentials + pub migrationkey_pub: IssuerPubKey, /// The public key of the BridgeDb issuing open invitations pub bridgedb_pub: PublicKey, @@ -185,10 +191,16 @@ pub struct BridgeAuth { /// The bridge table bridge_table: bridge_table::BridgeTable, + /// The migration table + migration_table: migration_table::MigrationTable, + /// Duplicate filter for open invitations openinv_filter: dup_filter::DupFilter, /// Duplicate filter for credential ids id_filter: dup_filter::DupFilter, + /// Duplicate filter for trust promotions (from untrusted level 0 to + /// trusted level 1) + trust_promotion_filter: dup_filter::DupFilter, /// For testing only: offset of the true time to the simulated time time_offset: time::Duration, @@ -196,19 +208,27 @@ pub struct BridgeAuth { impl BridgeAuth { pub fn new(bridgedb_pub: PublicKey) -> Self { + // Create the private and public keys for each of the types of + // credential, each with the appropriate number of attributes let lox_priv = IssuerPrivKey::new(6); let lox_pub = IssuerPubKey::new(&lox_priv); let migration_priv = IssuerPrivKey::new(3); let migration_pub = IssuerPubKey::new(&migration_priv); + let migrationkey_priv = IssuerPrivKey::new(2); + let migrationkey_pub = IssuerPubKey::new(&migrationkey_priv); Self { lox_priv, lox_pub, migration_priv, migration_pub, + migrationkey_priv, + migrationkey_pub, bridgedb_pub, bridge_table: Default::default(), + migration_table: Default::default(), openinv_filter: Default::default(), id_filter: Default::default(), + trust_promotion_filter: Default::default(), time_offset: time::Duration::zero(), } } @@ -284,4 +304,48 @@ mod tests { println!("cred = {:?}", cred); println!("bucket = {:?}", bucket); } + + #[test] + fn test_trust_promotion() { + // Create a BridegDb + let bdb = BridgeDb::new(15); + // Create a BridgeAuth + let mut ba = BridgeAuth::new(bdb.pubkey); + + // Make 15 buckets with one random bridge each + for _ in 0..15 { + let bucket: [BridgeLine; 3] = + [BridgeLine::random(), Default::default(), Default::default()]; + ba.bridge_table.new_bucket(bucket); + } + // Make 5 more buckets, each containing 3 of the previously + // created bridges + for i in 0u32..5 { + let iusize = i as usize; + let bucket: [BridgeLine; 3] = [ + ba.bridge_table.buckets[3 * iusize][0], + ba.bridge_table.buckets[3 * iusize + 1][0], + ba.bridge_table.buckets[3 * iusize + 2][0], + ]; + ba.bridge_table.new_bucket(bucket); + // Add the allowed migrations to the migration table + ba.migration_table.table.push((3 * i, 15 + i)); + ba.migration_table.table.push((3 * i + 1, 15 + i)); + ba.migration_table.table.push((3 * i + 2, 15 + i)); + } + // Create the encrypted bridge table + ba.bridge_table.encrypt_table(); + + // Issue an open invitation + let inv = bdb.invite(); + + // Use it to get a Lox credential + let (req, state) = open_invite::request(&inv); + let resp = ba.handle_open_invite(req).unwrap(); + let cred = + open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); + + // Time passes + ba.advance_days(40); + } } diff --git a/crates/lox-library/src/migration_table.rs b/crates/lox-library/src/migration_table.rs new file mode 100644 index 0000000..0937c76 --- /dev/null +++ b/crates/lox-library/src/migration_table.rs @@ -0,0 +1,15 @@ +/*! The migration table. + +This is a table listing pairs of (from_bucket_id, to_bucket_id). A pair +in this table indicates that a user with a Lox credential containing +from_bucket_id (and possibly meeting other conditions as well) is +entitled to exchange their credential for one with to_bucket_id. (Note +that the credentials contain the bucket attributes, which include both +the id and the bucket decrytpion key, but the table just contains the +bucket ids.) */ + +/// The migration table +#[derive(Default, Debug)] +pub struct MigrationTable { + pub table: Vec<(u32, u32)>, +} diff --git a/crates/lox-library/src/trust_promotion.rs b/crates/lox-library/src/trust_promotion.rs new file mode 100644 index 0000000..e090346 --- /dev/null +++ b/crates/lox-library/src/trust_promotion.rs @@ -0,0 +1,50 @@ +/*! A module for the protocol for the user to get promoted from +untrusted (trust level 0) to trusted (trust level 1). + +They are allowed to do this as long as UNTRUSTED_INTERVAL days have +passed since they obtained their level 0 Lox credential, and their +bridge (level 0 users get put in a one-bridge bucket) has not been +blocked. (Blocked bridges in one-bridge buckets will have their entries +removed from the bridge authority's migration table.) + +The user presents their current Lox credential: +- id: revealed +- bucket: blinded +- trust_level: revealed to be 0 +- level_since: blinded, but proved in ZK that it's at least + UNTRUSTED_INTERVAL days ago +- invites_remaining: revealed to be 0 +- invites_issued: revealed to be 0 + +They will receive in return the encrypted MAC (Pk, EncQk) for their +implicit Migration Key credential with attributes id and bucket, +along with a HashMap of encrypted Migration credentials. For each +(from_i, to_i) in the BA's migration list, there will be an entry in +the HashMap with key H1(id, from_attr_i, Qk_i) and value +Enc_{H2(id, from_attr_i, Qk_i)}(to_attr_i, P_i, Q_i). Here H1 and H2 +are the first 16 bytes and the second 16 bytes respectively of the +SHA256 hash of the input, P_i and Q_i are a MAC on the Migration +credential with attributes id, from_attr_i, and to_attr_i. Qk_i is the +value EncQk would decrypt to if bucket were equal to from_attr_i. */ + +use curve25519_dalek::ristretto::RistrettoBasepointTable; +use curve25519_dalek::ristretto::RistrettoPoint; +use curve25519_dalek::scalar::Scalar; +use curve25519_dalek::traits::IsIdentity; + +use zkp::CompactProof; +use zkp::ProofError; +use zkp::Transcript; + +/// The minimum number of days a user has to be at trust level 0 +/// (untrusted) with their (single) bridge unblocked before they can +/// move to level 1. +/// +/// The implementation also puts an upper bound of UNTRUSTED_INTERVAL + +/// 511 days, which is not unreasonable; we want users to be engaging +/// with the system in order to move up trust levels. +pub const UNTRUSTED_INTERVAL: u64 = 30; + +pub struct Request { + id: Scalar, +} From 9ed5d2158615222d64ea64b62502a5c29602966c Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Thu, 29 Apr 2021 16:12:53 -0400 Subject: [PATCH 017/115] Move unit tests to their own file --- crates/lox-library/src/lib.rs | 93 +-------------------------------- crates/lox-library/src/tests.rs | 90 +++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 91 deletions(-) create mode 100644 crates/lox-library/src/tests.rs diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 52159df..ab1d9e4 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -257,95 +257,6 @@ impl BridgeAuth { // The protocol modules pub mod open_invite; -// Unit tests that require access to the testing-only function -// BridgeLine::random() +// Unit tests #[cfg(test)] -mod tests { - use super::bridge_table::BridgeLine; - use super::*; - - #[test] - fn test_open_invite() { - // Create a BridegDb - let bdb = BridgeDb::new(20); - // Create a BridgeAuth - let mut ba = BridgeAuth::new(bdb.pubkey); - - // Make 20 buckets with one random bridge each - for _ in 0..20 { - let bucket: [BridgeLine; 3] = - [BridgeLine::random(), Default::default(), Default::default()]; - ba.bridge_table.new_bucket(bucket); - } - // And 20 more with three random bridges each - for _ in 0..20 { - let bucket: [BridgeLine; 3] = [ - BridgeLine::random(), - BridgeLine::random(), - BridgeLine::random(), - ]; - ba.bridge_table.new_bucket(bucket); - } - // Create the encrypted bridge table - ba.bridge_table.encrypt_table(); - - // Issue an open invitation - let inv = bdb.invite(); - - // Use it to get a Lox credential - let (req, state) = open_invite::request(&inv); - let resp = ba.handle_open_invite(req).unwrap(); - let cred = - open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); - - // Check that we can use the credential to read a bucket - let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); - let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap(); - println!("cred = {:?}", cred); - println!("bucket = {:?}", bucket); - } - - #[test] - fn test_trust_promotion() { - // Create a BridegDb - let bdb = BridgeDb::new(15); - // Create a BridgeAuth - let mut ba = BridgeAuth::new(bdb.pubkey); - - // Make 15 buckets with one random bridge each - for _ in 0..15 { - let bucket: [BridgeLine; 3] = - [BridgeLine::random(), Default::default(), Default::default()]; - ba.bridge_table.new_bucket(bucket); - } - // Make 5 more buckets, each containing 3 of the previously - // created bridges - for i in 0u32..5 { - let iusize = i as usize; - let bucket: [BridgeLine; 3] = [ - ba.bridge_table.buckets[3 * iusize][0], - ba.bridge_table.buckets[3 * iusize + 1][0], - ba.bridge_table.buckets[3 * iusize + 2][0], - ]; - ba.bridge_table.new_bucket(bucket); - // Add the allowed migrations to the migration table - ba.migration_table.table.push((3 * i, 15 + i)); - ba.migration_table.table.push((3 * i + 1, 15 + i)); - ba.migration_table.table.push((3 * i + 2, 15 + i)); - } - // Create the encrypted bridge table - ba.bridge_table.encrypt_table(); - - // Issue an open invitation - let inv = bdb.invite(); - - // Use it to get a Lox credential - let (req, state) = open_invite::request(&inv); - let resp = ba.handle_open_invite(req).unwrap(); - let cred = - open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); - - // Time passes - ba.advance_days(40); - } -} +mod tests; diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs new file mode 100644 index 0000000..4cdb51d --- /dev/null +++ b/crates/lox-library/src/tests.rs @@ -0,0 +1,90 @@ +/*! Unit tests that require access to the testing-only function +BridgeLine::random() or private fields */ + +use super::bridge_table::BridgeLine; +use super::*; + +#[test] +fn test_open_invite() { + // Create a BridegDb + let bdb = BridgeDb::new(20); + // Create a BridgeAuth + let mut ba = BridgeAuth::new(bdb.pubkey); + + // Make 20 buckets with one random bridge each + for _ in 0..20 { + let bucket: [BridgeLine; 3] = + [BridgeLine::random(), Default::default(), Default::default()]; + ba.bridge_table.new_bucket(bucket); + } + // And 20 more with three random bridges each + for _ in 0..20 { + let bucket: [BridgeLine; 3] = [ + BridgeLine::random(), + BridgeLine::random(), + BridgeLine::random(), + ]; + ba.bridge_table.new_bucket(bucket); + } + // Create the encrypted bridge table + ba.bridge_table.encrypt_table(); + + // Issue an open invitation + let inv = bdb.invite(); + + // Use it to get a Lox credential + let (req, state) = open_invite::request(&inv); + let resp = ba.handle_open_invite(req).unwrap(); + let cred = + open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); + + // Check that we can use the credential to read a bucket + let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); + let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap(); + println!("cred = {:?}", cred); + println!("bucket = {:?}", bucket); +} + +#[test] +fn test_trust_promotion() { + // Create a BridegDb + let bdb = BridgeDb::new(15); + // Create a BridgeAuth + let mut ba = BridgeAuth::new(bdb.pubkey); + + // Make 15 buckets with one random bridge each + for _ in 0..15 { + let bucket: [BridgeLine; 3] = + [BridgeLine::random(), Default::default(), Default::default()]; + ba.bridge_table.new_bucket(bucket); + } + // Make 5 more buckets, each containing 3 of the previously + // created bridges + for i in 0u32..5 { + let iusize = i as usize; + let bucket: [BridgeLine; 3] = [ + ba.bridge_table.buckets[3 * iusize][0], + ba.bridge_table.buckets[3 * iusize + 1][0], + ba.bridge_table.buckets[3 * iusize + 2][0], + ]; + ba.bridge_table.new_bucket(bucket); + // Add the allowed migrations to the migration table + ba.migration_table.table.push((3 * i, 15 + i)); + ba.migration_table.table.push((3 * i + 1, 15 + i)); + ba.migration_table.table.push((3 * i + 2, 15 + i)); + } + // Create the encrypted bridge table + ba.bridge_table.encrypt_table(); + + // Issue an open invitation + let inv = bdb.invite(); + + // Use it to get a Lox credential + let (req, state) = open_invite::request(&inv); + let resp = ba.handle_open_invite(req).unwrap(); + let cred = + open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); + + // Time passes + ba.advance_days(40); +} From 53652914ebfc1206482969b1ca29c2ace3c91ed4 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Thu, 29 Apr 2021 18:22:06 -0400 Subject: [PATCH 018/115] The request message of the trust promotion protocol --- crates/lox-library/src/lib.rs | 16 ++ crates/lox-library/src/tests.rs | 8 +- crates/lox-library/src/trust_promotion.rs | 316 ++++++++++++++++++++++ 3 files changed, 336 insertions(+), 4 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index ab1d9e4..a143361 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -35,6 +35,7 @@ use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; use ed25519_dalek::{Keypair, PublicKey, Signature, SignatureError, Signer, Verifier}; +use subtle::ConstantTimeEq; use lazy_static::lazy_static; @@ -254,6 +255,21 @@ impl BridgeAuth { } } +/// Try to extract a u64 from a Scalar +pub fn scalar_u64(s: &Scalar) -> Option { + // Check that the top 24 bytes of the Scalar are 0 + let sbytes = s.as_bytes(); + if sbytes[8..].ct_eq(&[0u8; 24]).unwrap_u8() == 0 { + return None; + } + Some(u64::from_le_bytes(sbytes[..8].try_into().unwrap())) +} + +/// Double a Scalar +pub fn scalar_dbl(s: &Scalar) -> Scalar { + s + s +} + // The protocol modules pub mod open_invite; diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 4cdb51d..2bc74c2 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -35,8 +35,7 @@ fn test_open_invite() { // Use it to get a Lox credential let (req, state) = open_invite::request(&inv); let resp = ba.handle_open_invite(req).unwrap(); - let cred = - open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); + let cred = open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); // Check that we can use the credential to read a bucket let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); @@ -82,9 +81,10 @@ fn test_trust_promotion() { // Use it to get a Lox credential let (req, state) = open_invite::request(&inv); let resp = ba.handle_open_invite(req).unwrap(); - let cred = - open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); + let cred = open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); // Time passes ba.advance_days(40); + + let (promreq, promstate) = trust_promotion::request(&cred, &ba.lox_pub, ba.today()).unwrap(); } diff --git a/crates/lox-library/src/trust_promotion.rs b/crates/lox-library/src/trust_promotion.rs index e090346..df1049f 100644 --- a/crates/lox-library/src/trust_promotion.rs +++ b/crates/lox-library/src/trust_promotion.rs @@ -36,6 +36,11 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; +use super::cred; +use super::IssuerPubKey; +use super::{scalar_dbl, scalar_u64}; +use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; + /// The minimum number of days a user has to be at trust level 0 /// (untrusted) with their (single) bridge unblocked before they can /// move to level 1. @@ -46,5 +51,316 @@ use zkp::Transcript; pub const UNTRUSTED_INTERVAL: u64 = 30; pub struct Request { + // Fields for blind showing the Lox credential + // We don't need to include trust_level, invites_remaining, or + // invites_issued, since they must be 0 + P: RistrettoPoint, id: Scalar, + CBucket: RistrettoPoint, + CSince: RistrettoPoint, + CQ: RistrettoPoint, + + // Fields for user blinding of the Migration Key credential + D: RistrettoPoint, + EncBucket: (RistrettoPoint, RistrettoPoint), + + // Fields for the inequality proof (level_since + + // UNTRUSTED_INTERVAL <= today) + CG1: RistrettoPoint, + CG2: RistrettoPoint, + CG3: RistrettoPoint, + CG4: RistrettoPoint, + CG5: RistrettoPoint, + CG6: RistrettoPoint, + CG7: RistrettoPoint, + CG8: RistrettoPoint, + + // The combined ZKP + piUser: CompactProof, +} + +#[derive(Debug)] +pub struct State { + d: Scalar, + D: RistrettoPoint, + EncBucket: (RistrettoPoint, RistrettoPoint), + id: Scalar, + bucket: Scalar, +} + +define_proof! { + requestproof, + "Trust Promotion Request", + (bucket, since, zbucket, zsince, negzQ, + d, ebucket, + g0, g1, g2, g3, g4, g5, g6, g7, g8, + zg0, zg1, zg2, zg3, zg4, zg5, zg6, zg7, zg8, + wg0, wg1, wg2, wg3, wg4, wg5, wg6, wg7, wg8, + yg0, yg1, yg2, yg3, yg4, yg5, yg6, yg7, yg8), + (P, CBucket, CSince, V, Xbucket, Xsince, + EncBucket0, EncBucket1, D, + CG0, CG1, CG2, CG3, CG4, CG5, CG6, CG7, CG8, + CG0sq, CG1sq, CG2sq, CG3sq, CG4sq, CG5sq, CG6sq, CG7sq, CG8sq), + (A, B): + // Blind showing of the Lox credential + CBucket = (bucket*P + zbucket*A), + CSince = (since*P + zsince*A), + V = (zbucket*Xbucket + zsince*Xsince + negzQ*A), + // User blinding of the Migration Key credential + EncBucket0 = (ebucket*B), + EncBucket1 = (bucket*B + ebucket*D), + D = (d*B), + // Prove CSince encodes a value at least UNTRUSTED_INTERVAL + // days ago (at technically at most UNTRUSTED_INTERVAL+511 days + // ago): first prove each of g0, ..., g8 is a bit by proving that + // gi = gi^2 + CG0 = (g0*P + zg0*A), CG0sq = (g0*CG0 + wg0*A), CG0sq = (g0*P + yg0*A), + CG1 = (g1*P + zg1*A), CG1sq = (g1*CG1 + wg1*A), CG1sq = (g1*P + yg1*A), + CG2 = (g2*P + zg2*A), CG2sq = (g2*CG2 + wg2*A), CG2sq = (g2*P + yg2*A), + CG3 = (g3*P + zg3*A), CG3sq = (g3*CG3 + wg3*A), CG3sq = (g3*P + yg3*A), + CG4 = (g4*P + zg4*A), CG4sq = (g4*CG4 + wg4*A), CG4sq = (g4*P + yg4*A), + CG5 = (g5*P + zg5*A), CG5sq = (g5*CG5 + wg5*A), CG5sq = (g5*P + yg5*A), + CG6 = (g6*P + zg6*A), CG6sq = (g6*CG6 + wg6*A), CG6sq = (g6*P + yg6*A), + CG7 = (g7*P + zg7*A), CG7sq = (g7*CG7 + wg7*A), CG7sq = (g7*P + yg7*A), + CG8 = (g8*P + zg8*A), CG8sq = (g8*CG8 + wg8*A), CG8sq = (g8*P + yg8*A) + // Then we'll check that CSince + UNTRUSTED_INTERVAL*P + CG0 + 2*CG1 + // + 4*CG2 + 8*CG3 + ... + 256*CG8 = today*P by having the verifier + // plug in today*P - (CSince + UNTRUSTED_INTERVAL*P + 2*CG1 + 4*CG2 + // + ... + 256*CG8) as its value of CG0. +} + +pub fn request( + lox_cred: &cred::Lox, + lox_pub: &IssuerPubKey, + today: u64, +) -> Result<(Request, State), ProofError> { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + // Ensure the credential can be correctly shown: it must be the case + // that level_since + UNTRUSTED_INTERVAL <= today. + let level_since: u64 = match scalar_u64(&lox_cred.level_since) { + Some(v) => v, + None => return Err(ProofError::VerificationFailure), + }; + if level_since + UNTRUSTED_INTERVAL > today { + return Err(ProofError::VerificationFailure); + } + let diffdays = today - (level_since + UNTRUSTED_INTERVAL); + if diffdays > 511 { + return Err(ProofError::VerificationFailure); + } + + // Blind showing the Lox credential + + // Reblind P and Q + let mut rng = rand::thread_rng(); + let t = Scalar::random(&mut rng); + let P = t * lox_cred.P; + let Q = t * lox_cred.Q; + + // Form Pedersen commitments to the blinded attributes + let zbucket = Scalar::random(&mut rng); + let zsince = Scalar::random(&mut rng); + let CBucket = lox_cred.bucket * P + &zbucket * Atable; + let CSince = lox_cred.level_since * P + &zsince * Atable; + + // Form a Pedersen commitment to the MAC Q + // We flip the sign of zQ from that of the Hyphae paper so that + // the ZKP has a "+" instead of a "-", as that's what the zkp + // macro supports. + let negzQ = Scalar::random(&mut rng); + let CQ = Q - &negzQ * Atable; + + // Compute the "error factor" + let V = zbucket * lox_pub.X[2] + zsince * lox_pub.X[4] + &negzQ * Atable; + + // User blinding the Migration Key credential + + // Pick an ElGamal keypair + let d = Scalar::random(&mut rng); + let D = &d * Btable; + + // Encrypt the attributes to be blinded (each times the + // basepoint B) to the public key we just created + let ebucket = Scalar::random(&mut rng); + let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D); + + // The range proof that 0 <= diffdays <= 511 + + // Extract the 9 bits from diffdays + let g0: Scalar = (diffdays & 1).into(); + let g1: Scalar = ((diffdays >> 1) & 1).into(); + let g2: Scalar = ((diffdays >> 2) & 1).into(); + let g3: Scalar = ((diffdays >> 3) & 1).into(); + let g4: Scalar = ((diffdays >> 4) & 1).into(); + let g5: Scalar = ((diffdays >> 5) & 1).into(); + let g6: Scalar = ((diffdays >> 6) & 1).into(); + let g7: Scalar = ((diffdays >> 7) & 1).into(); + let g8: Scalar = ((diffdays >> 8) & 1).into(); + + // Pick random factors for the Pedersen commitments + let wg0 = Scalar::random(&mut rng); + let zg1 = Scalar::random(&mut rng); + let wg1 = Scalar::random(&mut rng); + let zg2 = Scalar::random(&mut rng); + let wg2 = Scalar::random(&mut rng); + let zg3 = Scalar::random(&mut rng); + let wg3 = Scalar::random(&mut rng); + let zg4 = Scalar::random(&mut rng); + let wg4 = Scalar::random(&mut rng); + let zg5 = Scalar::random(&mut rng); + let wg5 = Scalar::random(&mut rng); + let zg6 = Scalar::random(&mut rng); + let wg6 = Scalar::random(&mut rng); + let zg7 = Scalar::random(&mut rng); + let wg7 = Scalar::random(&mut rng); + let zg8 = Scalar::random(&mut rng); + let wg8 = Scalar::random(&mut rng); + + // Compute zg0 to cancel things out as + // zg0 = -(zsince + 2*zg1 + 4*zg2 + 8*zg3 + 16*zg4 + 32*zg5 + 64*zg6 + 128*zg7 + 256*zg8) + // but use Horner's method + let zg0 = -scalar_dbl( + &(scalar_dbl( + &(scalar_dbl( + &(scalar_dbl( + &(scalar_dbl( + &(scalar_dbl(&(scalar_dbl(&(scalar_dbl(&zg8) + zg7)) + zg6)) + zg5), + ) + zg4), + ) + zg3), + ) + zg2), + ) + zg1), + ) + zsince; + + let yg0 = wg0 + g0 * zg0; + let yg1 = wg1 + g1 * zg1; + let yg2 = wg2 + g2 * zg2; + let yg3 = wg3 + g3 * zg3; + let yg4 = wg4 + g4 * zg4; + let yg5 = wg5 + g5 * zg5; + let yg6 = wg6 + g6 * zg6; + let yg7 = wg7 + g7 * zg7; + let yg8 = wg8 + g8 * zg8; + + let CG0 = g0 * P + &zg0 * Atable; + let CG1 = g1 * P + &zg1 * Atable; + let CG2 = g2 * P + &zg2 * Atable; + let CG3 = g3 * P + &zg3 * Atable; + let CG4 = g4 * P + &zg4 * Atable; + let CG5 = g5 * P + &zg5 * Atable; + let CG6 = g6 * P + &zg6 * Atable; + let CG7 = g7 * P + &zg7 * Atable; + let CG8 = g8 * P + &zg8 * Atable; + + // Construct the proof + let mut transcript = Transcript::new(b"trust promotion request"); + let piUser = requestproof::prove_compact( + &mut transcript, + requestproof::ProveAssignments { + A: &A, + B: &B, + P: &P, + CBucket: &CBucket, + CSince: &CSince, + V: &V, + Xbucket: &lox_pub.X[2], + Xsince: &lox_pub.X[4], + EncBucket0: &EncBucket.0, + EncBucket1: &EncBucket.1, + D: &D, + CG0: &CG0, + CG1: &CG1, + CG2: &CG2, + CG3: &CG3, + CG4: &CG4, + CG5: &CG5, + CG6: &CG6, + CG7: &CG7, + CG8: &CG8, + CG0sq: &(g0 * P + &yg0 * Atable), + CG1sq: &(g1 * P + &yg1 * Atable), + CG2sq: &(g2 * P + &yg2 * Atable), + CG3sq: &(g3 * P + &yg3 * Atable), + CG4sq: &(g4 * P + &yg4 * Atable), + CG5sq: &(g5 * P + &yg5 * Atable), + CG6sq: &(g6 * P + &yg6 * Atable), + CG7sq: &(g7 * P + &yg7 * Atable), + CG8sq: &(g8 * P + &yg8 * Atable), + bucket: &lox_cred.bucket, + since: &lox_cred.level_since, + zbucket: &zbucket, + zsince: &zsince, + negzQ: &negzQ, + d: &d, + ebucket: &ebucket, + g0: &g0, + g1: &g1, + g2: &g2, + g3: &g3, + g4: &g4, + g5: &g5, + g6: &g6, + g7: &g7, + g8: &g8, + zg0: &zg0, + zg1: &zg1, + zg2: &zg2, + zg3: &zg3, + zg4: &zg4, + zg5: &zg5, + zg6: &zg6, + zg7: &zg7, + zg8: &zg8, + wg0: &wg0, + wg1: &wg1, + wg2: &wg2, + wg3: &wg3, + wg4: &wg4, + wg5: &wg5, + wg6: &wg6, + wg7: &wg7, + wg8: &wg8, + yg0: &yg0, + yg1: &yg1, + yg2: &yg2, + yg3: &yg3, + yg4: &yg4, + yg5: &yg5, + yg6: &yg6, + yg7: &yg7, + yg8: &yg8, + }, + ) + .0; + + Ok(( + Request { + P, + id: lox_cred.id, + CBucket, + CSince, + CQ, + D, + EncBucket, + CG1, + CG2, + CG3, + CG4, + CG5, + CG6, + CG7, + CG8, + piUser, + }, + State { + d, + D, + EncBucket, + id: lox_cred.id, + bucket: lox_cred.bucket, + }, + )) } From 2ffa2c6ab082d6c91f7e9373ff60d051391df50d Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Thu, 29 Apr 2021 21:24:32 -0400 Subject: [PATCH 019/115] Check the proof in the request message of the trust promotion protocol --- crates/lox-library/Cargo.toml | 2 +- crates/lox-library/src/lib.rs | 21 ++++ crates/lox-library/src/tests.rs | 5 +- crates/lox-library/src/trust_promotion.rs | 132 +++++++++++++++++++--- crates/lox-library/tests/tests.rs | 8 -- 5 files changed, 145 insertions(+), 23 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index 9a2ffcb..a8cca5a 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] curve25519-dalek = { package = "curve25519-dalek-ng", version = "3", default-features = false, features = ["serde", "std"] } ed25519-dalek = "1" -zkp = "0.8" +zkp = { version = "0.8", features = ["debug-transcript"] } bincode = "1" rand = "0.7" serde = "1" diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index a143361..f6ca7f7 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -234,11 +234,13 @@ impl BridgeAuth { } } + #[cfg(test)] /// For testing only: manually advance the day by 1 day pub fn advance_day(&mut self) { self.time_offset += time::Duration::days(1); } + #[cfg(test)] /// For testing only: manually advance the day by the given number /// of days pub fn advance_days(&mut self, days: u16) { @@ -253,6 +255,20 @@ impl BridgeAuth { .try_into() .unwrap() } + + #[cfg(test)] + /// Verify the MAC on a Lox credential + pub fn verify_lox(&self, cred: &cred::Lox) -> bool { + let Q = (self.lox_priv.x[0] + + cred.id * self.lox_priv.x[1] + + cred.bucket * self.lox_priv.x[2] + + cred.trust_level * self.lox_priv.x[3] + + cred.level_since * self.lox_priv.x[4] + + cred.invites_remaining * self.lox_priv.x[5] + + cred.invites_issued * self.lox_priv.x[6]) + * cred.P; + return Q == cred.Q; + } } /// Try to extract a u64 from a Scalar @@ -270,6 +286,11 @@ pub fn scalar_dbl(s: &Scalar) -> Scalar { s + s } +/// Double a RistrettoPoint +pub fn pt_dbl(P: &RistrettoPoint) -> RistrettoPoint { + P + P +} + // The protocol modules pub mod open_invite; diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 2bc74c2..2c09007 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -42,6 +42,7 @@ fn test_open_invite() { let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap(); println!("cred = {:?}", cred); println!("bucket = {:?}", bucket); + assert!(ba.verify_lox(&cred)); } #[test] @@ -82,9 +83,11 @@ fn test_trust_promotion() { let (req, state) = open_invite::request(&inv); let resp = ba.handle_open_invite(req).unwrap(); let cred = open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); + assert!(ba.verify_lox(&cred)); // Time passes - ba.advance_days(40); + ba.advance_days(47); let (promreq, promstate) = trust_promotion::request(&cred, &ba.lox_pub, ba.today()).unwrap(); + let resp = ba.handle_trust_promotion(promreq).unwrap(); } diff --git a/crates/lox-library/src/trust_promotion.rs b/crates/lox-library/src/trust_promotion.rs index df1049f..2fc9074 100644 --- a/crates/lox-library/src/trust_promotion.rs +++ b/crates/lox-library/src/trust_promotion.rs @@ -37,8 +37,8 @@ use zkp::ProofError; use zkp::Transcript; use super::cred; -use super::IssuerPubKey; -use super::{scalar_dbl, scalar_u64}; +use super::{pt_dbl, scalar_dbl, scalar_u64}; +use super::{BridgeAuth, IssuerPubKey}; use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; /// The minimum number of days a user has to be at trust level 0 @@ -74,6 +74,15 @@ pub struct Request { CG6: RistrettoPoint, CG7: RistrettoPoint, CG8: RistrettoPoint, + CG0sq: RistrettoPoint, + CG1sq: RistrettoPoint, + CG2sq: RistrettoPoint, + CG3sq: RistrettoPoint, + CG4sq: RistrettoPoint, + CG5sq: RistrettoPoint, + CG6sq: RistrettoPoint, + CG7sq: RistrettoPoint, + CG8sq: RistrettoPoint, // The combined ZKP piUser: CompactProof, @@ -223,7 +232,7 @@ pub fn request( // Compute zg0 to cancel things out as // zg0 = -(zsince + 2*zg1 + 4*zg2 + 8*zg3 + 16*zg4 + 32*zg5 + 64*zg6 + 128*zg7 + 256*zg8) // but use Horner's method - let zg0 = -scalar_dbl( + let zg0 = -(scalar_dbl( &(scalar_dbl( &(scalar_dbl( &(scalar_dbl( @@ -233,7 +242,7 @@ pub fn request( ) + zg3), ) + zg2), ) + zg1), - ) + zsince; + ) + zsince); let yg0 = wg0 + g0 * zg0; let yg1 = wg1 + g1 * zg1; @@ -255,6 +264,16 @@ pub fn request( let CG7 = g7 * P + &zg7 * Atable; let CG8 = g8 * P + &zg8 * Atable; + let CG0sq = g0 * P + &yg0 * Atable; + let CG1sq = g1 * P + &yg1 * Atable; + let CG2sq = g2 * P + &yg2 * Atable; + let CG3sq = g3 * P + &yg3 * Atable; + let CG4sq = g4 * P + &yg4 * Atable; + let CG5sq = g5 * P + &yg5 * Atable; + let CG6sq = g6 * P + &yg6 * Atable; + let CG7sq = g7 * P + &yg7 * Atable; + let CG8sq = g8 * P + &yg8 * Atable; + // Construct the proof let mut transcript = Transcript::new(b"trust promotion request"); let piUser = requestproof::prove_compact( @@ -280,15 +299,15 @@ pub fn request( CG6: &CG6, CG7: &CG7, CG8: &CG8, - CG0sq: &(g0 * P + &yg0 * Atable), - CG1sq: &(g1 * P + &yg1 * Atable), - CG2sq: &(g2 * P + &yg2 * Atable), - CG3sq: &(g3 * P + &yg3 * Atable), - CG4sq: &(g4 * P + &yg4 * Atable), - CG5sq: &(g5 * P + &yg5 * Atable), - CG6sq: &(g6 * P + &yg6 * Atable), - CG7sq: &(g7 * P + &yg7 * Atable), - CG8sq: &(g8 * P + &yg8 * Atable), + CG0sq: &CG0sq, + CG1sq: &CG1sq, + CG2sq: &CG2sq, + CG3sq: &CG3sq, + CG4sq: &CG4sq, + CG5sq: &CG5sq, + CG6sq: &CG6sq, + CG7sq: &CG7sq, + CG8sq: &CG8sq, bucket: &lox_cred.bucket, since: &lox_cred.level_since, zbucket: &zbucket, @@ -353,6 +372,15 @@ pub fn request( CG6, CG7, CG8, + CG0sq, + CG1sq, + CG2sq, + CG3sq, + CG4sq, + CG5sq, + CG6sq, + CG7sq, + CG8sq, piUser, }, State { @@ -364,3 +392,81 @@ pub fn request( }, )) } + +impl BridgeAuth { + /// Receive a trust promotion request + pub fn handle_trust_promotion(&mut self, req: Request) -> Result<(), ProofError> { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + + if req.P.is_identity() { + return Err(ProofError::VerificationFailure); + } + + // Recompute the "error factor" using knowledge of our own + // (the issuer's) private key instead of knowledge of the + // hidden attributes + let Vprime = (self.lox_priv.x[0] + self.lox_priv.x[1] * req.id) * req.P + + self.lox_priv.x[2] * req.CBucket + + self.lox_priv.x[4] * req.CSince + - req.CQ; + + // Recompute CG0 using Horner's method + let today: Scalar = self.today().into(); + let unt: Scalar = UNTRUSTED_INTERVAL.into(); + let CG0prime = (today - unt) * req.P + - req.CSince + - pt_dbl( + &(pt_dbl( + &(pt_dbl( + &(pt_dbl( + &(pt_dbl( + &(pt_dbl(&(pt_dbl(&(pt_dbl(&req.CG8) + req.CG7)) + req.CG6)) + + req.CG5), + ) + req.CG4), + ) + req.CG3), + ) + req.CG2), + ) + req.CG1), + ); + + // Verify the ZKP + let mut transcript = Transcript::new(b"trust promotion request"); + requestproof::verify_compact( + &req.piUser, + &mut transcript, + requestproof::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P: &req.P.compress(), + CBucket: &req.CBucket.compress(), + CSince: &req.CSince.compress(), + V: &Vprime.compress(), + Xbucket: &self.lox_pub.X[2].compress(), + Xsince: &self.lox_pub.X[4].compress(), + EncBucket0: &req.EncBucket.0.compress(), + EncBucket1: &req.EncBucket.1.compress(), + D: &req.D.compress(), + CG0: &CG0prime.compress(), + CG1: &req.CG1.compress(), + CG2: &req.CG2.compress(), + CG3: &req.CG3.compress(), + CG4: &req.CG4.compress(), + CG5: &req.CG5.compress(), + CG6: &req.CG6.compress(), + CG7: &req.CG7.compress(), + CG8: &req.CG8.compress(), + CG0sq: &req.CG0sq.compress(), + CG1sq: &req.CG1sq.compress(), + CG2sq: &req.CG2sq.compress(), + CG3sq: &req.CG3sq.compress(), + CG4sq: &req.CG4sq.compress(), + CG5sq: &req.CG5sq.compress(), + CG6sq: &req.CG6sq.compress(), + CG7sq: &req.CG7sq.compress(), + CG8sq: &req.CG8sq.compress(), + }, + )?; + + Ok(()) + } +} diff --git a/crates/lox-library/tests/tests.rs b/crates/lox-library/tests/tests.rs index bc2c799..163bac5 100644 --- a/crates/lox-library/tests/tests.rs +++ b/crates/lox-library/tests/tests.rs @@ -45,11 +45,3 @@ fn test_dup_filter() { println!("df1 = {:?}", df1); println!("df2 = {:?}", df2); } - -#[test] -fn test_bridgeauth() { - let bdb = BridgeDb::new(20); - let mut ba = BridgeAuth::new(bdb.pubkey); - ba.advance_day(); - ba.advance_days(30); -} From 03de724a8c07658a2d8bfb526b286f5eb54275de Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Fri, 30 Apr 2021 11:58:31 -0400 Subject: [PATCH 020/115] The response message of the trust promotion protocol --- crates/lox-library/Cargo.toml | 3 +- crates/lox-library/src/bridge_table.rs | 4 +- crates/lox-library/src/migration_table.rs | 157 +++++++++++++++++++++- crates/lox-library/src/open_invite.rs | 2 +- crates/lox-library/src/tests.rs | 7 +- crates/lox-library/src/trust_promotion.rs | 61 ++++++++- crates/lox-library/tests/tests.rs | 1 - 7 files changed, 224 insertions(+), 11 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index a8cca5a..ea88540 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -7,7 +7,8 @@ edition = "2018" [dependencies] curve25519-dalek = { package = "curve25519-dalek-ng", version = "3", default-features = false, features = ["serde", "std"] } ed25519-dalek = "1" -zkp = { version = "0.8", features = ["debug-transcript"] } +# zkp = { version = "0.8", features = ["debug-transcript"] } +zkp = "0.8" bincode = "1" rand = "0.7" serde = "1" diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index 3abc640..39b8683 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -252,11 +252,11 @@ mod tests { } /// Convert an id and key to a Scalar attribute -pub fn to_scalar(id: u32, key: [u8; 16]) -> Scalar { +pub fn to_scalar(id: u32, key: &[u8; 16]) -> Scalar { let mut b: [u8; 32] = [0; 32]; // b is a little-endian representation of the Scalar; put the key in // the low 16 bytes, and the id in the next 4 bytes. - b[0..16].copy_from_slice(&key); + b[0..16].copy_from_slice(key); b[16..20].copy_from_slice(&id.to_le_bytes()); // This cannot fail, since we're only using the low 20 bytes of b Scalar::from_canonical_bytes(b).unwrap() diff --git a/crates/lox-library/src/migration_table.rs b/crates/lox-library/src/migration_table.rs index 0937c76..ac13f83 100644 --- a/crates/lox-library/src/migration_table.rs +++ b/crates/lox-library/src/migration_table.rs @@ -8,8 +8,163 @@ that the credentials contain the bucket attributes, which include both the id and the bucket decrytpion key, but the table just contains the bucket ids.) */ +use curve25519_dalek::ristretto::RistrettoBasepointTable; +use curve25519_dalek::scalar::Scalar; + +use sha2::Digest; +use sha2::Sha256; + +use aes_gcm::aead::{generic_array::GenericArray, Aead, NewAead}; +use aes_gcm::Aes128Gcm; +use rand::RngCore; + +use std::collections::HashMap; + +use super::bridge_table; +use super::IssuerPrivKey; +use super::CMZ_B_TABLE; + +/// Each (plaintext) entry in the returned migration table is serialized +/// into this many bytes +pub const MIGRATION_BYTES: usize = 96; + +/// The size of an encrypted entry in the returned migration table +pub const ENC_MIGRATION_BYTES: usize = MIGRATION_BYTES + 12 + 16; + /// The migration table #[derive(Default, Debug)] pub struct MigrationTable { - pub table: Vec<(u32, u32)>, + pub table: HashMap, +} + +/// Create an encrypted Migration credential for returning to the user +/// in the trust promotion protocol. +/// +/// Given the attributes of a Migration credential, produce a serialized +/// version (containing only the to_bucket and the MAC, since the +/// receiver will already know the id and from_bucket), encrypted with +/// H2(id, from_bucket, Qk), for the Qk portion of the MAC on the +/// corresponding Migration Key credential (with fixed Pk, given as a +/// precomputed multiplication table). Return the label H1(id, +/// from_attr_i, Qk_i) and the encrypted Migration credential. H1 and +/// H2 are the first 16 bytes and the second 16 bytes respectively of +/// the SHA256 hash of the input. +pub fn encrypt_cred( + id: &Scalar, + from_bucket: &Scalar, + to_bucket: &Scalar, + Pktable: &RistrettoBasepointTable, + migration_priv: &IssuerPrivKey, + migrationkey_priv: &IssuerPrivKey, +) -> ([u8; 16], [u8; ENC_MIGRATION_BYTES]) { + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + let mut rng = rand::thread_rng(); + + // Compute the Migration Key credential MAC Qk + let Qk = &(migrationkey_priv.x[0] + + migrationkey_priv.x[1] * id + + migrationkey_priv.x[2] * from_bucket) + * Pktable; + + // Compute a MAC (P, Q) on the Migration credential + let b = Scalar::random(&mut rng); + let P = &b * Btable; + let Q = &(b + * (migration_priv.x[0] + + migration_priv.x[1] * id + + migration_priv.x[2] * from_bucket + + migration_priv.x[3] * to_bucket)) + * Btable; + + // Serialize (to_bucket, P, Q) + let mut credbytes: [u8; MIGRATION_BYTES] = [0; MIGRATION_BYTES]; + credbytes[0..32].copy_from_slice(&to_bucket.as_bytes()[..]); + credbytes[32..64].copy_from_slice(&P.compress().as_bytes()[..]); + credbytes[64..].copy_from_slice(&Q.compress().as_bytes()[..]); + + // Pick a random nonce + let mut noncebytes: [u8; 12] = [0; 12]; + rng.fill_bytes(&mut noncebytes); + let nonce = GenericArray::from_slice(&noncebytes); + + // Compute the hash of (id, from_bucket, Qk) + let mut hasher = Sha256::new(); + hasher.update(&id.as_bytes()[..]); + hasher.update(&from_bucket.as_bytes()[..]); + hasher.update(&Qk.compress().as_bytes()[..]); + let fullhash = hasher.finalize(); + + // Create the encryption key from the 2nd half of the hash + let aeskey = GenericArray::from_slice(&fullhash[16..]); + // Encrypt + let cipher = Aes128Gcm::new(aeskey); + let ciphertext: Vec = cipher.encrypt(&nonce, credbytes.as_ref()).unwrap(); + let mut enccredbytes: [u8; ENC_MIGRATION_BYTES] = [0; ENC_MIGRATION_BYTES]; + enccredbytes[..12].copy_from_slice(&noncebytes); + enccredbytes[12..].copy_from_slice(ciphertext.as_slice()); + + // Use the first half of the above hash as the label + let mut label: [u8; 16] = [0; 16]; + label[..].copy_from_slice(&fullhash[..16]); + + (label, enccredbytes) +} + +/// Create an encrypted Migration credential for returning to the user +/// in the trust promotion protocol, given the ids of the from and to +/// buckets, and using a BridgeTable to get the bucket keys. +/// +/// Otherwise the same as encrypt_cred, above, except it returns an +/// Option in case the passed ids were invalid. +pub fn encrypt_cred_ids( + id: &Scalar, + from_id: u32, + to_id: u32, + bridgetable: &bridge_table::BridgeTable, + Pktable: &RistrettoBasepointTable, + migration_priv: &IssuerPrivKey, + migrationkey_priv: &IssuerPrivKey, +) -> Option<([u8; 16], [u8; ENC_MIGRATION_BYTES])> { + // Look up the bucket keys and form the attributes (Scalars) + let fromkey = bridgetable.keys.get(from_id as usize)?; + let tokey = bridgetable.keys.get(to_id as usize)?; + Some(encrypt_cred( + id, + &bridge_table::to_scalar(from_id, fromkey), + &bridge_table::to_scalar(to_id, tokey), + Pktable, + migration_priv, + migrationkey_priv, + )) +} + +impl MigrationTable { + /// For each entry in the MigrationTable, use encrypt_cred_ids to + /// produce an entry in an output HashMap (from labels to encrypted + /// Migration credentials). + pub fn encrypt_table( + &self, + id: &Scalar, + bridgetable: &bridge_table::BridgeTable, + Pktable: &RistrettoBasepointTable, + migration_priv: &IssuerPrivKey, + migrationkey_priv: &IssuerPrivKey, + ) -> HashMap<[u8; 16], [u8; ENC_MIGRATION_BYTES]> { + self.table + .iter() + .map(|(from_id, to_id)| { + encrypt_cred_ids( + id, + *from_id, + *to_id, + bridgetable, + Pktable, + migration_priv, + migrationkey_priv, + ) + .unwrap() + }) + .collect() + } } diff --git a/crates/lox-library/src/open_invite.rs b/crates/lox-library/src/open_invite.rs index cef5dcd..b5e47ed 100644 --- a/crates/lox-library/src/open_invite.rs +++ b/crates/lox-library/src/open_invite.rs @@ -203,7 +203,7 @@ impl BridgeAuth { // Create the bucket attribute (Scalar), which is a combination // of the bucket id (u32) and the bucket's decryption key ([u8; 16]) let bucket_key = self.bridge_table.keys[bucket_id]; - let bucket: Scalar = bridge_table::to_scalar(bucket_id_u32, bucket_key); + let bucket: Scalar = bridge_table::to_scalar(bucket_id_u32, &bucket_key); // Create the level_since attribute (Scalar), which is today's // Julian date diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 2c09007..4b30929 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -69,9 +69,9 @@ fn test_trust_promotion() { ]; ba.bridge_table.new_bucket(bucket); // Add the allowed migrations to the migration table - ba.migration_table.table.push((3 * i, 15 + i)); - ba.migration_table.table.push((3 * i + 1, 15 + i)); - ba.migration_table.table.push((3 * i + 2, 15 + i)); + ba.migration_table.table.insert(3 * i, 15 + i); + ba.migration_table.table.insert(3 * i + 1, 15 + i); + ba.migration_table.table.insert(3 * i + 2, 15 + i); } // Create the encrypted bridge table ba.bridge_table.encrypt_table(); @@ -90,4 +90,5 @@ fn test_trust_promotion() { let (promreq, promstate) = trust_promotion::request(&cred, &ba.lox_pub, ba.today()).unwrap(); let resp = ba.handle_trust_promotion(promreq).unwrap(); + println!("resp = {:?}", resp); } diff --git a/crates/lox-library/src/trust_promotion.rs b/crates/lox-library/src/trust_promotion.rs index 2fc9074..3f0bad2 100644 --- a/crates/lox-library/src/trust_promotion.rs +++ b/crates/lox-library/src/trust_promotion.rs @@ -36,7 +36,11 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; +use std::collections::HashMap; + use super::cred; +use super::dup_filter::SeenType; +use super::migration_table; use super::{pt_dbl, scalar_dbl, scalar_u64}; use super::{BridgeAuth, IssuerPubKey}; use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; @@ -97,6 +101,18 @@ pub struct State { bucket: Scalar, } +#[derive(Debug)] +pub struct Response { + // The encrypted MAC for the Migration Key credential + Pk: RistrettoPoint, + EncQk: (RistrettoPoint, RistrettoPoint), + + // A table of encrypted Migration credentials; the encryption keys + // are formed from the possible values of Qk (the decrypted form of + // EncQk) + enc_migration_table: HashMap<[u8; 16], [u8; migration_table::ENC_MIGRATION_BYTES]>, +} + define_proof! { requestproof, "Trust Promotion Request", @@ -395,9 +411,10 @@ pub fn request( impl BridgeAuth { /// Receive a trust promotion request - pub fn handle_trust_promotion(&mut self, req: Request) -> Result<(), ProofError> { + pub fn handle_trust_promotion(&mut self, req: Request) -> Result { let A: &RistrettoPoint = &CMZ_A; let B: &RistrettoPoint = &CMZ_B; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; if req.P.is_identity() { return Err(ProofError::VerificationFailure); @@ -467,6 +484,46 @@ impl BridgeAuth { }, )?; - Ok(()) + // Ensure the id has not been seen before, either in the general + // if filter, or the filter specifically for trust promotion. + // Add the id to the latter, but not the former. + if self.id_filter.check(&req.id) == SeenType::Seen + || self.trust_promotion_filter.filter(&req.id) == SeenType::Seen + { + return Err(ProofError::VerificationFailure); + } + + // Compute the encrypted MAC (Pk, EncQk) for the Migration Key + // credential. + + // Compute the MAC on the visible attributes + let mut rng = rand::thread_rng(); + let b = Scalar::random(&mut rng); + let Pk = &b * Btable; + let Pktable = RistrettoBasepointTable::create(&Pk); + let Qid = &(self.migrationkey_priv.x[0] + self.migrationkey_priv.x[1] * req.id) * &Pktable; + + // El Gamal encrypt it to the public key req.D + let s = Scalar::random(&mut rng); + let EncQkid = (&s * Btable, Qid + s * req.D); + + // Homomorphically compute the part of the MAC corresponding to + // the blinded attributes + let tbucket = self.migrationkey_priv.x[2] * b; + let EncQkBucket = (tbucket * req.EncBucket.0, tbucket * req.EncBucket.1); + + let EncQk = (EncQkid.0 + EncQkBucket.0, EncQkid.1 + EncQkBucket.1); + + Ok(Response { + Pk, + EncQk, + enc_migration_table: self.migration_table.encrypt_table( + &req.id, + &self.bridge_table, + &Pktable, + &self.migration_priv, + &self.migrationkey_priv, + ), + }) } } diff --git a/crates/lox-library/tests/tests.rs b/crates/lox-library/tests/tests.rs index 163bac5..cdd1abd 100644 --- a/crates/lox-library/tests/tests.rs +++ b/crates/lox-library/tests/tests.rs @@ -1,6 +1,5 @@ use lox::dup_filter; use lox::dup_filter::SeenType::{Fresh, Seen}; -use lox::BridgeAuth; use lox::BridgeDb; use curve25519_dalek::scalar::Scalar; From 6013386f070e1c34f9119c237ccc0d7a75b28378 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Fri, 30 Apr 2021 13:30:20 -0400 Subject: [PATCH 021/115] Handle the response of the trust promotion protocol to produce the Migration credential --- crates/lox-library/src/lib.rs | 11 +++++ crates/lox-library/src/migration_table.rs | 52 +++++++++++++++++++++++ crates/lox-library/src/tests.rs | 11 ++++- crates/lox-library/src/trust_promotion.rs | 20 +++++++++ 4 files changed, 92 insertions(+), 2 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index f6ca7f7..934a159 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -269,6 +269,17 @@ impl BridgeAuth { * cred.P; return Q == cred.Q; } + + #[cfg(test)] + /// Verify the MAC on a Migration credential + pub fn verify_migration(&self, cred: &cred::Migration) -> bool { + let Q = (self.migration_priv.x[0] + + cred.lox_id * self.migration_priv.x[1] + + cred.from_bucket * self.migration_priv.x[2] + + cred.to_bucket * self.migration_priv.x[3]) + * cred.P; + return Q == cred.Q; + } } /// Try to extract a u64 from a Scalar diff --git a/crates/lox-library/src/migration_table.rs b/crates/lox-library/src/migration_table.rs index ac13f83..081da54 100644 --- a/crates/lox-library/src/migration_table.rs +++ b/crates/lox-library/src/migration_table.rs @@ -8,7 +8,9 @@ that the credentials contain the bucket attributes, which include both the id and the bucket decrytpion key, but the table just contains the bucket ids.) */ +use curve25519_dalek::ristretto::CompressedRistretto; use curve25519_dalek::ristretto::RistrettoBasepointTable; +use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; use sha2::Digest; @@ -21,6 +23,7 @@ use rand::RngCore; use std::collections::HashMap; use super::bridge_table; +use super::cred::Migration; use super::IssuerPrivKey; use super::CMZ_B_TABLE; @@ -168,3 +171,52 @@ impl MigrationTable { .collect() } } + +/// Decrypt an encrypted Migration credential given Qk, the known +/// attributes id and from_bucket for the Migration credential, and a +/// HashMap mapping labels to ciphertexts. +pub fn decrypt_cred( + Qk: &RistrettoPoint, + lox_id: &Scalar, + from_bucket: &Scalar, + enc_migration_table: &HashMap<[u8; 16], [u8; ENC_MIGRATION_BYTES]>, +) -> Option { + // Compute the hash of (id, from_bucket, Qk) + let mut hasher = Sha256::new(); + hasher.update(&lox_id.as_bytes()[..]); + hasher.update(&from_bucket.as_bytes()[..]); + hasher.update(&Qk.compress().as_bytes()[..]); + let fullhash = hasher.finalize(); + + // Use the first half of the above hash as the label + let mut label: [u8; 16] = [0; 16]; + label[..].copy_from_slice(&fullhash[..16]); + + // Look up the label in the HashMap + let ciphertext = enc_migration_table.get(&label)?; + + // Create the decryption key from the 2nd half of the hash + let aeskey = GenericArray::from_slice(&fullhash[16..]); + + // Decrypt + let nonce = GenericArray::from_slice(&ciphertext[..12]); + let cipher = Aes128Gcm::new(aeskey); + let plaintext: Vec = match cipher.decrypt(&nonce, ciphertext[12..].as_ref()) { + Ok(v) => v, + Err(_) => return None, + }; + let plaintextbytes = plaintext.as_slice(); + let mut to_bucket_bytes: [u8; 32] = [0; 32]; + to_bucket_bytes.copy_from_slice(&plaintextbytes[..32]); + let to_bucket = Scalar::from_bytes_mod_order(to_bucket_bytes); + let P = CompressedRistretto::from_slice(&plaintextbytes[32..64]).decompress()?; + let Q = CompressedRistretto::from_slice(&plaintextbytes[64..]).decompress()?; + + Some(Migration { + P, + Q, + lox_id: *lox_id, + from_bucket: *from_bucket, + to_bucket, + }) +} diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 4b30929..c7d31cb 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -89,6 +89,13 @@ fn test_trust_promotion() { ba.advance_days(47); let (promreq, promstate) = trust_promotion::request(&cred, &ba.lox_pub, ba.today()).unwrap(); - let resp = ba.handle_trust_promotion(promreq).unwrap(); - println!("resp = {:?}", resp); + let promresp = ba.handle_trust_promotion(promreq).unwrap(); + let migcred = trust_promotion::handle_response(promstate, promresp).unwrap(); + println!("resp = {:?}", migcred); + assert!(ba.verify_migration(&migcred)); + // Check that we can use the to_bucket in the Migration credenital + // to read a bucket + let (id, key) = bridge_table::from_scalar(migcred.to_bucket).unwrap(); + let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap(); + println!("bucket = {:?}", bucket); } diff --git a/crates/lox-library/src/trust_promotion.rs b/crates/lox-library/src/trust_promotion.rs index 3f0bad2..93ee51f 100644 --- a/crates/lox-library/src/trust_promotion.rs +++ b/crates/lox-library/src/trust_promotion.rs @@ -527,3 +527,23 @@ impl BridgeAuth { }) } } + +/// Handle the response to the request, producing a Migration credential +/// if successful. +/// +/// The Migration credential can then be used in the migration protocol +/// to actually upgrade to trust level 1. +pub fn handle_response(state: State, resp: Response) -> Result { + if resp.Pk.is_identity() { + return Err(ProofError::VerificationFailure); + } + + // Decrypt the MAC on the Migration Key credential + let Qk = resp.EncQk.1 - (state.d * resp.EncQk.0); + + // Use Qk to locate and decrypt the Migration credential + match migration_table::decrypt_cred(&Qk, &state.id, &state.bucket, &resp.enc_migration_table) { + Some(m) => Ok(m), + None => Err(ProofError::VerificationFailure), + } +} From 83b12ff6f688a20ce6536f12982d84195e2a4c99 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Fri, 30 Apr 2021 16:24:42 -0400 Subject: [PATCH 022/115] The complete migration protocol for the case of migrating from trust level 0 to trust level 1 --- crates/lox-library/src/lib.rs | 24 +- crates/lox-library/src/migration.rs | 612 ++++++++++++++++++++++++++++ crates/lox-library/src/tests.rs | 37 +- 3 files changed, 667 insertions(+), 6 deletions(-) create mode 100644 crates/lox-library/src/migration.rs diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 934a159..ae2fcd7 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -21,7 +21,6 @@ pub mod bridge_table; pub mod cred; pub mod dup_filter; pub mod migration_table; -pub mod trust_promotion; use sha2::Sha512; @@ -33,6 +32,8 @@ use curve25519_dalek::constants as dalek_constants; use curve25519_dalek::ristretto::RistrettoBasepointTable; use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; +#[cfg(test)] +use curve25519_dalek::traits::IsIdentity; use ed25519_dalek::{Keypair, PublicKey, Signature, SignatureError, Signer, Verifier}; use subtle::ConstantTimeEq; @@ -257,8 +258,12 @@ impl BridgeAuth { } #[cfg(test)] - /// Verify the MAC on a Lox credential + /// Verify the two MACs on a Lox credential pub fn verify_lox(&self, cred: &cred::Lox) -> bool { + if cred.P.is_identity() || cred.P_noopmigration.is_identity() { + return false; + } + let Q = (self.lox_priv.x[0] + cred.id * self.lox_priv.x[1] + cred.bucket * self.lox_priv.x[2] @@ -267,12 +272,23 @@ impl BridgeAuth { + cred.invites_remaining * self.lox_priv.x[5] + cred.invites_issued * self.lox_priv.x[6]) * cred.P; - return Q == cred.Q; + + let Q_noopmigration = (self.migration_priv.x[0] + + cred.id * self.migration_priv.x[1] + + cred.bucket * self.migration_priv.x[2] + + cred.bucket * self.migration_priv.x[3]) + * cred.P_noopmigration; + + return Q == cred.Q && Q_noopmigration == cred.Q_noopmigration; } #[cfg(test)] /// Verify the MAC on a Migration credential pub fn verify_migration(&self, cred: &cred::Migration) -> bool { + if cred.P.is_identity() { + return false; + } + let Q = (self.migration_priv.x[0] + cred.lox_id * self.migration_priv.x[1] + cred.from_bucket * self.migration_priv.x[2] @@ -303,7 +319,9 @@ pub fn pt_dbl(P: &RistrettoPoint) -> RistrettoPoint { } // The protocol modules +pub mod migration; pub mod open_invite; +pub mod trust_promotion; // Unit tests #[cfg(test)] diff --git a/crates/lox-library/src/migration.rs b/crates/lox-library/src/migration.rs new file mode 100644 index 0000000..4450fdc --- /dev/null +++ b/crates/lox-library/src/migration.rs @@ -0,0 +1,612 @@ +/*! A module for the protocol for the user to migrate from one bucket to +another (and possibly also change trust level). + +For the case of migrating from trust level 0 (a one-bridge bucket) to +trust level 1 (a three-bridge bucket), the user presents their current +Lox credential: + +- id: revealed +- bucket: blinded +- trust_level: revealed to be 0 +- level_since: blinded +- invites_remaining: revealed to be 0 +- invites_issued: revealed to be 0 + +and a Migration credential: + +- id: revealed as the same as the Lox credential id above +- from_bucket: blinded, but proved in ZK that it's the same as the + bucket in the Lox credential above +- to_bucket: blinded + +and a new Lox credential to be issued: + +- id: jointly chosen by the user and BA +- bucket: blinded, but proved in ZK that it's the same as the to_bucket + in the Migration credential above +- trust_level: 1 +- level_since: today +- invites_remaining: 0 +- invites_issued: 0 + +*/ + +use curve25519_dalek::ristretto::RistrettoBasepointTable; +use curve25519_dalek::ristretto::RistrettoPoint; +use curve25519_dalek::scalar::Scalar; +use curve25519_dalek::traits::IsIdentity; + +use zkp::CompactProof; +use zkp::ProofError; +use zkp::Transcript; + +use super::cred; +use super::{BridgeAuth, IssuerPubKey}; +use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; + +pub struct Request { + // Fields for blind showing the Lox credential + // We don't need to include invites_remaining or invites_issued, + // since they must be 0 + P_lox: RistrettoPoint, + id: Scalar, + CBucket: RistrettoPoint, + trust_level: Scalar, + CSince: RistrettoPoint, + CQ_lox: RistrettoPoint, + + // Fields for blind showing the Migration credential + P_mig: RistrettoPoint, + CFromBucket: RistrettoPoint, + CToBucket: RistrettoPoint, + CQ_mig: RistrettoPoint, + + // Fields for user blinding of the Lox credential to be issued + D: RistrettoPoint, + EncIdClient: (RistrettoPoint, RistrettoPoint), + EncBucket: (RistrettoPoint, RistrettoPoint), + + // The combined ZKP + piUser: CompactProof, +} + +#[derive(Debug)] +pub struct State { + d: Scalar, + D: RistrettoPoint, + EncIdClient: (RistrettoPoint, RistrettoPoint), + EncBucket: (RistrettoPoint, RistrettoPoint), + id_client: Scalar, + to_bucket: Scalar, +} + +pub struct Response { + // The new attributes; trust_level = 1 is implicit + level_since: Scalar, + + // The fields for the new Lox credential + P: RistrettoPoint, + EncQ: (RistrettoPoint, RistrettoPoint), + id_server: Scalar, + TId: RistrettoPoint, + TBucket: RistrettoPoint, + + // The fields for the implicit noop migration ("nm") credential + P_nm: RistrettoPoint, + EncQ_nm: (RistrettoPoint, RistrettoPoint), + TId_nm: RistrettoPoint, + TBucket_nm: RistrettoPoint, + + // The ZKP + piBlindIssue: CompactProof, +} + +define_proof! { + requestproof, + "Migration Request", + (bucket, since, zbucket, zsince, negzQ_lox, + tobucket, zfrombucket, ztobucket, negzQ_mig, + d, eid_client, ebucket, id_client), + (P_lox, CBucket, CSince, V_lox, Xbucket, Xsince, + P_mig, CFromBucket, CToBucket, V_mig, Xfrombucket, Xtobucket, + D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1), + (A, B): + // Blind showing of the Lox credential + CBucket = (bucket*P_lox + zbucket*A), + CSince = (since*P_lox + zsince*A), + V_lox = (zbucket*Xbucket + zsince*Xsince + negzQ_lox*A), + // Blind showing of the Migration credential; note the use of the + // same "bucket" secret variable + CFromBucket = (bucket*P_mig + zfrombucket*A), + CToBucket = (tobucket*P_mig + ztobucket*A), + V_mig = (zfrombucket*Xfrombucket + ztobucket*Xtobucket + negzQ_mig*A), + // User blinding of the Lox credential to be issued; note the use of + // the same "tobucket" secret variable + EncIdClient0 = (eid_client*B), + EncIdClient1 = (id_client*B + eid_client*D), + EncBucket0 = (ebucket*B), + EncBucket1 = (tobucket*B + ebucket*D), + D = (d*B) +} + +define_proof! { + blindissue, + "Migration Blind Issuing", + (x0, x0tilde, xid, xbucket, xlevel, xsince, s, b, tid, tbucket, + x0_nm, x0tilde_nm, xid_nm, xfrom_nm, xto_nm, s_nm, b_nm, tid_nm, tbucket_nm), + (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xlevel, Xsince, Plevel, Psince, TId, TBucket, + P_nm, EncQ0_nm, EncQ1_nm, X0_nm, Xid_nm, Xfrom_nm, Xto_nm, + TId_nm, TBucket_nm, + D, EncId0, EncId1, EncBucket0, EncBucket1), + (A, B): + Xid = (xid*A), + Xlevel = (xlevel*A), + Xbucket = (xbucket*A), + Xsince = (xsince*A), + X0 = (x0*B + x0tilde*A), + P = (b*B), + TId = (b*Xid), + TId = (tid*A), + TBucket = (b*Xbucket), + TBucket = (tbucket*A), + EncQ0 = (s*B + tid*EncId0 + tbucket*EncBucket0), + EncQ1 = (s*D + tid*EncId1 + tbucket*EncBucket1 + x0*P + xlevel*Plevel + xsince*Psince), + Xid_nm = (xid_nm*A), + Xfrom_nm = (xfrom_nm*A), + Xto_nm = (xto_nm*A), + X0_nm = (x0_nm*B + x0tilde_nm*A), + P_nm = (b_nm*B), + TId_nm = (b_nm*Xid_nm), + TId_nm = (tid_nm*A), + TBucket_nm = (b_nm*Xfrom_nm + b_nm*Xto_nm), + TBucket_nm = (tbucket_nm*A), + EncQ0_nm = (s_nm*B + tid_nm*EncId0 + tbucket_nm*EncBucket0), + EncQ1_nm = (s_nm*D + tid_nm*EncId1 + tbucket_nm*EncBucket1 + x0_nm*P_nm) +} + +pub fn request( + lox_cred: &cred::Lox, + migration_cred: &cred::Migration, + lox_pub: &IssuerPubKey, + migration_pub: &IssuerPubKey, +) -> Result<(Request, State), ProofError> { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + // Ensure that the credenials can be correctly shown; that is, the + // ids match and the Lox credential bucket matches the Migration + // credential from_bucket + if lox_cred.id != migration_cred.lox_id || lox_cred.bucket != migration_cred.from_bucket { + return Err(ProofError::VerificationFailure); + } + + // We only support migrating from trust level 0 to trust level 1 + // right now + if lox_cred.trust_level != Scalar::zero() { + return Err(ProofError::VerificationFailure); + } + + // Blind showing the Lox credential + + // Reblind P and Q + let mut rng = rand::thread_rng(); + let t_lox = Scalar::random(&mut rng); + let P_lox = t_lox * lox_cred.P; + let Q_lox = t_lox * lox_cred.Q; + + // Form Pedersen commitments to the blinded attributes + let zbucket = Scalar::random(&mut rng); + let zsince = Scalar::random(&mut rng); + let CBucket = lox_cred.bucket * P_lox + &zbucket * Atable; + let CSince = lox_cred.level_since * P_lox + &zsince * Atable; + + // Form a Pedersen commitment to the MAC Q + // We flip the sign of zQ from that of the Hyphae paper so that + // the ZKP has a "+" instead of a "-", as that's what the zkp + // macro supports. + let negzQ_lox = Scalar::random(&mut rng); + let CQ_lox = Q_lox - &negzQ_lox * Atable; + + // Compute the "error factor" + let V_lox = zbucket * lox_pub.X[2] + zsince * lox_pub.X[4] + &negzQ_lox * Atable; + + // Blind showing the Migration credential + + // Reblind P and Q + let t_mig = Scalar::random(&mut rng); + let P_mig = t_mig * migration_cred.P; + let Q_mig = t_mig * migration_cred.Q; + + // Form Pedersen commitments to the blinded attributes + let zfrombucket = Scalar::random(&mut rng); + let ztobucket = Scalar::random(&mut rng); + let CFromBucket = migration_cred.from_bucket * P_mig + &zfrombucket * Atable; + let CToBucket = migration_cred.to_bucket * P_mig + &ztobucket * Atable; + + // Form a Pedersen commitment to the MAC Q + // We flip the sign of zQ from that of the Hyphae paper so that + // the ZKP has a "+" instead of a "-", as that's what the zkp + // macro supports. + let negzQ_mig = Scalar::random(&mut rng); + let CQ_mig = Q_mig - &negzQ_mig * Atable; + + // Compute the "error factor" + let V_mig = + zfrombucket * migration_pub.X[2] + ztobucket * migration_pub.X[3] + &negzQ_mig * Atable; + + // User blinding for the Lox certificate to be issued + + // Pick an ElGamal keypair + let d = Scalar::random(&mut rng); + let D = &d * Btable; + + // Pick a random client component of the id + let id_client = Scalar::random(&mut rng); + + // Encrypt it (times the basepoint B) to the ElGamal public key D we + // just created + let eid_client = Scalar::random(&mut rng); + let EncIdClient = (&eid_client * Btable, &id_client * Btable + eid_client * D); + + // Encrypt the bucket field (times B) to D as well + let ebucket = Scalar::random(&mut rng); + let EncBucket = ( + &ebucket * Btable, + &migration_cred.to_bucket * Btable + ebucket * D, + ); + + // Construct the proof + let mut transcript = Transcript::new(b"migration request"); + let piUser = requestproof::prove_compact( + &mut transcript, + requestproof::ProveAssignments { + A: &A, + B: &B, + P_lox: &P_lox, + CBucket: &CBucket, + CSince: &CSince, + V_lox: &V_lox, + Xbucket: &lox_pub.X[2], + Xsince: &lox_pub.X[4], + P_mig: &P_mig, + CFromBucket: &CFromBucket, + CToBucket: &CToBucket, + V_mig: &V_mig, + Xfrombucket: &migration_pub.X[2], + Xtobucket: &migration_pub.X[3], + D: &D, + EncIdClient0: &EncIdClient.0, + EncIdClient1: &EncIdClient.1, + EncBucket0: &EncBucket.0, + EncBucket1: &EncBucket.1, + bucket: &lox_cred.bucket, + since: &lox_cred.level_since, + zbucket: &zbucket, + zsince: &zsince, + negzQ_lox: &negzQ_lox, + tobucket: &migration_cred.to_bucket, + zfrombucket: &zfrombucket, + ztobucket: &ztobucket, + negzQ_mig: &negzQ_mig, + d: &d, + eid_client: &eid_client, + ebucket: &ebucket, + id_client: &id_client, + }, + ) + .0; + + Ok(( + Request { + P_lox, + id: lox_cred.id, + CBucket, + trust_level: lox_cred.trust_level, + CSince, + CQ_lox, + P_mig, + CFromBucket, + CToBucket, + CQ_mig, + D, + EncIdClient, + EncBucket, + piUser, + }, + State { + d, + D, + EncIdClient, + EncBucket, + id_client, + to_bucket: migration_cred.to_bucket, + }, + )) +} + +impl BridgeAuth { + /// Receive a migration request + pub fn handle_migration(&mut self, req: Request) -> Result { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + if req.P_lox.is_identity() || req.P_mig.is_identity() { + return Err(ProofError::VerificationFailure); + } + + // We only currently support migrating from trust level 0 + if req.trust_level != Scalar::zero() { + return Err(ProofError::VerificationFailure); + } + + // Recompute the "error factors" using knowledge of our own + // (the issuer's) private key instead of knowledge of the + // hidden attributes + let Vprime_lox = (self.lox_priv.x[0] + + self.lox_priv.x[1] * req.id + + self.lox_priv.x[3] * req.trust_level) + * req.P_lox + + self.lox_priv.x[2] * req.CBucket + + self.lox_priv.x[4] * req.CSince + - req.CQ_lox; + + let Vprime_mig = (self.migration_priv.x[0] + self.migration_priv.x[1] * req.id) * req.P_mig + + self.migration_priv.x[2] * req.CFromBucket + + self.migration_priv.x[3] * req.CToBucket + - req.CQ_mig; + + // Verify the ZKP + let mut transcript = Transcript::new(b"migration request"); + requestproof::verify_compact( + &req.piUser, + &mut transcript, + requestproof::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P_lox: &req.P_lox.compress(), + CBucket: &req.CBucket.compress(), + CSince: &req.CSince.compress(), + V_lox: &Vprime_lox.compress(), + Xbucket: &self.lox_pub.X[2].compress(), + Xsince: &self.lox_pub.X[4].compress(), + P_mig: &req.P_mig.compress(), + CFromBucket: &req.CFromBucket.compress(), + CToBucket: &req.CToBucket.compress(), + V_mig: &Vprime_mig.compress(), + Xfrombucket: &self.migration_pub.X[2].compress(), + Xtobucket: &self.migration_pub.X[3].compress(), + D: &req.D.compress(), + EncIdClient0: &req.EncIdClient.0.compress(), + EncIdClient1: &req.EncIdClient.1.compress(), + EncBucket0: &req.EncBucket.0.compress(), + EncBucket1: &req.EncBucket.1.compress(), + }, + )?; + + // Blind issuing of the new Lox credential + + // Choose a random server id component to add to the client's + // (blinded) id component + let mut rng = rand::thread_rng(); + let id_server = Scalar::random(&mut rng); + let EncId = (req.EncIdClient.0, req.EncIdClient.1 + &id_server * Btable); + + // Create the trust_level attrubute (Scalar), which will be + // level 1 + let trust_level: Scalar = Scalar::one(); + + // Create the level_since attribute (Scalar), which is today's + // Julian date + let level_since: Scalar = self.today().into(); + + // The invitations_remaining and invitations_issued attributes + // are 0 for level 0 and level 1 Lox credentials, so we don't + // need to explicitly create them. + + // Compute the MAC on the visible attributes + let b = Scalar::random(&mut rng); + let P = &b * Btable; + // invites_remaining = invites_issued = 0 + let QHc = (self.lox_priv.x[0] + + self.lox_priv.x[3] * trust_level + + self.lox_priv.x[4] * level_since) + * P; + + // El Gamal encrypt it to the public key req.D + let s = Scalar::random(&mut rng); + let EncQHc = (&s * Btable, QHc + s * req.D); + + // Homomorphically compute the part of the MAC corresponding to + // the blinded id attribute + let tid = self.lox_priv.x[1] * b; + let TId = &tid * Atable; + let EncQId = (tid * EncId.0, tid * EncId.1); + let tbucket = self.lox_priv.x[2] * b; + let TBucket = &tbucket * Atable; + let EncQBucket = (tbucket * req.EncBucket.0, tbucket * req.EncBucket.1); + + let EncQ = ( + EncQHc.0 + EncQId.0 + EncQBucket.0, + EncQHc.1 + EncQId.1 + EncQBucket.1, + ); + + // Now the no-op migration credential + // Compute the MAC on the visible attributes (none here) + let b_nm = Scalar::random(&mut rng); + let P_nm = &b_nm * Btable; + let QHc_nm = (self.migration_priv.x[0]) * P_nm; + + // El Gamal encrypt it to the public key req.D + let s_nm = Scalar::random(&mut rng); + let EncQHc_nm = (&s_nm * Btable, QHc_nm + s_nm * req.D); + + // Homomorphically compute the part of the MAC corresponding to + // the blinded attributes + let tid_nm = self.migration_priv.x[1] * b_nm; + let TId_nm = &tid_nm * Atable; + let EncQId_nm = (tid_nm * EncId.0, tid_nm * EncId.1); + let tbucket_nm = (self.migration_priv.x[2] + self.migration_priv.x[3]) * b_nm; + let TBucket_nm = &tbucket_nm * Atable; + let EncQBucket_nm = (tbucket_nm * req.EncBucket.0, tbucket_nm * req.EncBucket.1); + + let EncQ_nm = ( + EncQHc_nm.0 + EncQId_nm.0 + EncQBucket_nm.0, + EncQHc_nm.1 + EncQId_nm.1 + EncQBucket_nm.1, + ); + + let mut transcript = Transcript::new(b"migration issuing"); + let piBlindIssue = blindissue::prove_compact( + &mut transcript, + blindissue::ProveAssignments { + A: &A, + B: &B, + P: &P, + EncQ0: &EncQ.0, + EncQ1: &EncQ.1, + X0: &self.lox_pub.X[0], + Xid: &self.lox_pub.X[1], + Xbucket: &self.lox_pub.X[2], + Xlevel: &self.lox_pub.X[3], + Xsince: &self.lox_pub.X[4], + Plevel: &(trust_level * P), + Psince: &(level_since * P), + TId: &TId, + TBucket: &TBucket, + P_nm: &P_nm, + EncQ0_nm: &EncQ_nm.0, + EncQ1_nm: &EncQ_nm.1, + X0_nm: &self.migration_pub.X[0], + Xid_nm: &self.migration_pub.X[1], + Xfrom_nm: &self.migration_pub.X[2], + Xto_nm: &self.migration_pub.X[3], + TId_nm: &TId_nm, + TBucket_nm: &TBucket_nm, + D: &req.D, + EncId0: &EncId.0, + EncId1: &EncId.1, + EncBucket0: &req.EncBucket.0, + EncBucket1: &req.EncBucket.1, + x0: &self.lox_priv.x[0], + x0tilde: &self.lox_priv.x0tilde, + xid: &self.lox_priv.x[1], + xbucket: &self.lox_priv.x[2], + xlevel: &self.lox_priv.x[3], + xsince: &self.lox_priv.x[4], + s: &s, + b: &b, + tid: &tid, + tbucket: &tbucket, + x0_nm: &self.migration_priv.x[0], + x0tilde_nm: &self.migration_priv.x0tilde, + xid_nm: &self.migration_priv.x[1], + xfrom_nm: &self.migration_priv.x[2], + xto_nm: &self.migration_priv.x[3], + s_nm: &s_nm, + b_nm: &b_nm, + tid_nm: &tid_nm, + tbucket_nm: &tbucket_nm, + }, + ) + .0; + + Ok(Response { + level_since, + P, + EncQ, + id_server, + TId, + TBucket, + P_nm, + EncQ_nm, + TId_nm, + TBucket_nm, + piBlindIssue, + }) + } +} + +/// Handle the response to the request, producing the new Lox credential +/// if successful. +pub fn handle_response( + state: State, + resp: Response, + lox_pub: &IssuerPubKey, + migration_pub: &IssuerPubKey, +) -> Result { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + if resp.P.is_identity() || resp.P_nm.is_identity() { + return Err(ProofError::VerificationFailure); + } + + // Add the server's contribution to the id to our own, both in plain + // and encrypted form + let id = state.id_client + resp.id_server; + let EncId = ( + state.EncIdClient.0, + state.EncIdClient.1 + &resp.id_server * Btable, + ); + + // Verify the proof + let mut transcript = Transcript::new(b"migration issuing"); + blindissue::verify_compact( + &resp.piBlindIssue, + &mut transcript, + blindissue::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P: &resp.P.compress(), + EncQ0: &resp.EncQ.0.compress(), + EncQ1: &resp.EncQ.1.compress(), + X0: &lox_pub.X[0].compress(), + Xid: &lox_pub.X[1].compress(), + Xbucket: &lox_pub.X[2].compress(), + Xlevel: &lox_pub.X[3].compress(), + Xsince: &lox_pub.X[4].compress(), + // The new trust level is 1 + Plevel: &(Scalar::one() * resp.P).compress(), + Psince: &(resp.level_since * resp.P).compress(), + TId: &resp.TId.compress(), + TBucket: &resp.TBucket.compress(), + P_nm: &resp.P_nm.compress(), + EncQ0_nm: &resp.EncQ_nm.0.compress(), + EncQ1_nm: &resp.EncQ_nm.1.compress(), + X0_nm: &migration_pub.X[0].compress(), + Xid_nm: &migration_pub.X[1].compress(), + Xfrom_nm: &migration_pub.X[2].compress(), + Xto_nm: &migration_pub.X[3].compress(), + TId_nm: &resp.TId_nm.compress(), + TBucket_nm: &resp.TBucket_nm.compress(), + D: &state.D.compress(), + EncId0: &EncId.0.compress(), + EncId1: &EncId.1.compress(), + EncBucket0: &state.EncBucket.0.compress(), + EncBucket1: &state.EncBucket.1.compress(), + }, + )?; + + // Decrypt EncQ + let Q = resp.EncQ.1 - (state.d * resp.EncQ.0); + + // Decrypt EncQ_nm + let Q_nm = resp.EncQ_nm.1 - (state.d * resp.EncQ_nm.0); + + Ok(cred::Lox { + P: resp.P, + Q, + id, + bucket: state.to_bucket, + trust_level: Scalar::one(), + level_since: resp.level_since, + invites_remaining: Scalar::zero(), + invites_issued: Scalar::zero(), + P_noopmigration: resp.P_nm, + Q_noopmigration: Q_nm, + }) +} diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index c7d31cb..3d2db6e 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -45,8 +45,7 @@ fn test_open_invite() { assert!(ba.verify_lox(&cred)); } -#[test] -fn test_trust_promotion() { +fn setup() -> (BridgeDb, BridgeAuth) { // Create a BridegDb let bdb = BridgeDb::new(15); // Create a BridgeAuth @@ -76,6 +75,10 @@ fn test_trust_promotion() { // Create the encrypted bridge table ba.bridge_table.encrypt_table(); + (bdb, ba) +} + +fn trust_promotion(bdb: &BridgeDb, ba: &mut BridgeAuth) -> (cred::Lox, cred::Migration) { // Issue an open invitation let inv = bdb.invite(); @@ -91,7 +94,16 @@ fn test_trust_promotion() { let (promreq, promstate) = trust_promotion::request(&cred, &ba.lox_pub, ba.today()).unwrap(); let promresp = ba.handle_trust_promotion(promreq).unwrap(); let migcred = trust_promotion::handle_response(promstate, promresp).unwrap(); - println!("resp = {:?}", migcred); + + (cred, migcred) +} + +#[test] +fn test_trust_promotion() { + let (bdb, mut ba) = setup(); + + let (_loxcred, migcred) = trust_promotion(&bdb, &mut ba); + assert!(ba.verify_migration(&migcred)); // Check that we can use the to_bucket in the Migration credenital // to read a bucket @@ -99,3 +111,22 @@ fn test_trust_promotion() { let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap(); println!("bucket = {:?}", bucket); } + +#[test] +fn test_level0_migration() { + let (bdb, mut ba) = setup(); + + let (loxcred, migcred) = trust_promotion(&bdb, &mut ba); + + let (migreq, migstate) = + migration::request(&loxcred, &migcred, &ba.lox_pub, &ba.migration_pub).unwrap(); + let migresp = ba.handle_migration(migreq).unwrap(); + let newloxcred = + migration::handle_response(migstate, migresp, &ba.lox_pub, &ba.migration_pub).unwrap(); + assert!(ba.verify_lox(&newloxcred)); + println!("newloxcred = {:?}", newloxcred); + // Check that we can use the credenital to read a bucket + let (id, key) = bridge_table::from_scalar(newloxcred.bucket).unwrap(); + let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap(); + println!("bucket = {:?}", bucket); +} From 7f07951668635882d092443722265f83f97bb6e7 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Fri, 30 Apr 2021 16:44:53 -0400 Subject: [PATCH 023/115] Don't forget to check the credential against the seen list --- crates/lox-library/src/migration.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/lox-library/src/migration.rs b/crates/lox-library/src/migration.rs index 4450fdc..8e096fb 100644 --- a/crates/lox-library/src/migration.rs +++ b/crates/lox-library/src/migration.rs @@ -41,6 +41,7 @@ use zkp::ProofError; use zkp::Transcript; use super::cred; +use super::dup_filter::SeenType; use super::{BridgeAuth, IssuerPubKey}; use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; @@ -387,6 +388,12 @@ impl BridgeAuth { }, )?; + // Ensure the id has not been seen before, and add it to the + // seen list. + if self.id_filter.filter(&req.id) == SeenType::Seen { + return Err(ProofError::VerificationFailure); + } + // Blind issuing of the new Lox credential // Choose a random server id component to add to the client's From ab864fae45e21cae497133507fbbd90438958cf1 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Sat, 1 May 2021 11:56:25 -0400 Subject: [PATCH 024/115] Handle the case where the migration table has illegal entries for some reason --- crates/lox-library/src/migration_table.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/lox-library/src/migration_table.rs b/crates/lox-library/src/migration_table.rs index 081da54..7973d7a 100644 --- a/crates/lox-library/src/migration_table.rs +++ b/crates/lox-library/src/migration_table.rs @@ -156,7 +156,7 @@ impl MigrationTable { ) -> HashMap<[u8; 16], [u8; ENC_MIGRATION_BYTES]> { self.table .iter() - .map(|(from_id, to_id)| { + .filter_map(|(from_id, to_id)| { encrypt_cred_ids( id, *from_id, @@ -166,7 +166,6 @@ impl MigrationTable { migration_priv, migrationkey_priv, ) - .unwrap() }) .collect() } From 8a19376edc61a4a68208f3663482d0954a02440f Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Sat, 1 May 2021 15:21:50 -0400 Subject: [PATCH 025/115] Moved protocol modules into submodules of "proto" module instead of all being at the top level --- crates/lox-library/src/lib.rs | 19 +++++++++++---- .../lox-library/src/{ => proto}/migration.rs | 8 +++---- .../src/{ => proto}/open_invite.rs | 24 +++++++++---------- .../src/{ => proto}/trust_promotion.rs | 12 +++++----- crates/lox-library/src/tests.rs | 1 + 5 files changed, 38 insertions(+), 26 deletions(-) rename crates/lox-library/src/{ => proto}/migration.rs (99%) rename crates/lox-library/src/{ => proto}/open_invite.rs (95%) rename crates/lox-library/src/{ => proto}/trust_promotion.rs (98%) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index ae2fcd7..2b481c9 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -318,10 +318,21 @@ pub fn pt_dbl(P: &RistrettoPoint) -> RistrettoPoint { P + P } -// The protocol modules -pub mod migration; -pub mod open_invite; -pub mod trust_promotion; +/// The protocol modules. +/// +/// 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 +/// that consumes a Request and produces a Result. +pub mod proto { + pub mod migration; + pub mod open_invite; + pub mod trust_promotion; +} // Unit tests #[cfg(test)] diff --git a/crates/lox-library/src/migration.rs b/crates/lox-library/src/proto/migration.rs similarity index 99% rename from crates/lox-library/src/migration.rs rename to crates/lox-library/src/proto/migration.rs index 8e096fb..72964ee 100644 --- a/crates/lox-library/src/migration.rs +++ b/crates/lox-library/src/proto/migration.rs @@ -40,10 +40,10 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; -use super::cred; -use super::dup_filter::SeenType; -use super::{BridgeAuth, IssuerPubKey}; -use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; +use super::super::cred; +use super::super::dup_filter::SeenType; +use super::super::{BridgeAuth, IssuerPubKey}; +use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; pub struct Request { // Fields for blind showing the Lox credential diff --git a/crates/lox-library/src/open_invite.rs b/crates/lox-library/src/proto/open_invite.rs similarity index 95% rename from crates/lox-library/src/open_invite.rs rename to crates/lox-library/src/proto/open_invite.rs index b5e47ed..b88f66e 100644 --- a/crates/lox-library/src/open_invite.rs +++ b/crates/lox-library/src/proto/open_invite.rs @@ -22,15 +22,16 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; -use super::bridge_table; -use super::cred; -use super::dup_filter::SeenType; -use super::{BridgeAuth, IssuerPubKey}; -use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; +use super::super::bridge_table; +use super::super::cred; +use super::super::dup_filter::SeenType; +use super::super::OPENINV_LENGTH; +use super::super::{BridgeAuth, BridgeDb, IssuerPubKey}; +use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; /// The request message for this protocol pub struct Request { - invite: [u8; super::OPENINV_LENGTH], + invite: [u8; OPENINV_LENGTH], D: RistrettoPoint, EncIdClient: (RistrettoPoint, RistrettoPoint), piUserBlinding: CompactProof, @@ -104,7 +105,7 @@ define_proof! { /// Submit an open invitation issued by the BridgeDb to receive your /// first Lox credential -pub fn request(invite: &[u8; super::OPENINV_LENGTH]) -> (Request, State) { +pub fn request(invite: &[u8; OPENINV_LENGTH]) -> (Request, State) { let B: &RistrettoPoint = &CMZ_B; let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; @@ -159,11 +160,10 @@ impl BridgeAuth { // Check the signature on the open_invite. We manually match // here because we're changing the Err type from SignatureError // to ProofError - let (invite_id, bucket_id_u32) = - match super::BridgeDb::verify(req.invite, self.bridgedb_pub) { - Ok(res) => res, - Err(_) => return Err(ProofError::VerificationFailure), - }; + let (invite_id, bucket_id_u32) = match BridgeDb::verify(req.invite, self.bridgedb_pub) { + Ok(res) => res, + Err(_) => return Err(ProofError::VerificationFailure), + }; let bucket_id: usize = bucket_id_u32 as usize; // Only proceed if the invite_id is fresh diff --git a/crates/lox-library/src/trust_promotion.rs b/crates/lox-library/src/proto/trust_promotion.rs similarity index 98% rename from crates/lox-library/src/trust_promotion.rs rename to crates/lox-library/src/proto/trust_promotion.rs index 93ee51f..b84a80b 100644 --- a/crates/lox-library/src/trust_promotion.rs +++ b/crates/lox-library/src/proto/trust_promotion.rs @@ -38,12 +38,12 @@ use zkp::Transcript; use std::collections::HashMap; -use super::cred; -use super::dup_filter::SeenType; -use super::migration_table; -use super::{pt_dbl, scalar_dbl, scalar_u64}; -use super::{BridgeAuth, IssuerPubKey}; -use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; +use super::super::cred; +use super::super::dup_filter::SeenType; +use super::super::migration_table; +use super::super::{pt_dbl, scalar_dbl, scalar_u64}; +use super::super::{BridgeAuth, IssuerPubKey}; +use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; /// The minimum number of days a user has to be at trust level 0 /// (untrusted) with their (single) bridge unblocked before they can diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 3d2db6e..aec5c37 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -2,6 +2,7 @@ BridgeLine::random() or private fields */ use super::bridge_table::BridgeLine; +use super::proto::*; use super::*; #[test] From 33f3de3b681d3011be40460e57675949e496db5a Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Sat, 1 May 2021 15:33:45 -0400 Subject: [PATCH 026/115] Dates should just be u32, not u64 --- crates/lox-library/src/lib.rs | 13 ++++++++++++- crates/lox-library/src/proto/trust_promotion.rs | 8 ++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 2b481c9..8ada29e 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -249,8 +249,9 @@ impl BridgeAuth { } /// Get today's (real or simulated) date - fn today(&self) -> u64 { + fn today(&self) -> u32 { // We will not encounter negative Julian dates (~6700 years ago) + // or ones larger than 32 bits (time::OffsetDateTime::now_utc().date() + self.time_offset) .julian_day() .try_into() @@ -308,6 +309,16 @@ pub fn scalar_u64(s: &Scalar) -> Option { Some(u64::from_le_bytes(sbytes[..8].try_into().unwrap())) } +/// Try to extract a u32 from a Scalar +pub fn scalar_u32(s: &Scalar) -> Option { + // Check that the top 28 bytes of the Scalar are 0 + let sbytes = s.as_bytes(); + if sbytes[4..].ct_eq(&[0u8; 28]).unwrap_u8() == 0 { + return None; + } + Some(u32::from_le_bytes(sbytes[..4].try_into().unwrap())) +} + /// Double a Scalar pub fn scalar_dbl(s: &Scalar) -> Scalar { s + s diff --git a/crates/lox-library/src/proto/trust_promotion.rs b/crates/lox-library/src/proto/trust_promotion.rs index b84a80b..6c4ddac 100644 --- a/crates/lox-library/src/proto/trust_promotion.rs +++ b/crates/lox-library/src/proto/trust_promotion.rs @@ -41,7 +41,7 @@ use std::collections::HashMap; use super::super::cred; use super::super::dup_filter::SeenType; use super::super::migration_table; -use super::super::{pt_dbl, scalar_dbl, scalar_u64}; +use super::super::{pt_dbl, scalar_dbl, scalar_u32}; use super::super::{BridgeAuth, IssuerPubKey}; use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; @@ -52,7 +52,7 @@ use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; /// The implementation also puts an upper bound of UNTRUSTED_INTERVAL + /// 511 days, which is not unreasonable; we want users to be engaging /// with the system in order to move up trust levels. -pub const UNTRUSTED_INTERVAL: u64 = 30; +pub const UNTRUSTED_INTERVAL: u32 = 30; pub struct Request { // Fields for blind showing the Lox credential @@ -157,7 +157,7 @@ define_proof! { pub fn request( lox_cred: &cred::Lox, lox_pub: &IssuerPubKey, - today: u64, + today: u32, ) -> Result<(Request, State), ProofError> { let A: &RistrettoPoint = &CMZ_A; let B: &RistrettoPoint = &CMZ_B; @@ -166,7 +166,7 @@ pub fn request( // Ensure the credential can be correctly shown: it must be the case // that level_since + UNTRUSTED_INTERVAL <= today. - let level_since: u64 = match scalar_u64(&lox_cred.level_since) { + let level_since: u32 = match scalar_u32(&lox_cred.level_since) { Some(v) => v, None => return Err(ProofError::VerificationFailure), }; From ba13545b3cda5aef4cec322cd80cf1f7be3d1ae3 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Sat, 1 May 2021 17:12:03 -0400 Subject: [PATCH 027/115] Create Bucket Reachability credentials and put them in buckets as appropriate --- crates/lox-library/src/bridge_table.rs | 154 +++++++++++++++++++++---- crates/lox-library/src/cred.rs | 79 ++++++++----- crates/lox-library/src/lib.rs | 36 ++++++ crates/lox-library/src/tests.rs | 16 ++- 4 files changed, 228 insertions(+), 57 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index 39b8683..43823be 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -8,11 +8,17 @@ buckets. Users will either download the whole encrypted bucket list or use PIR to download a piece of it, so that the bridge authority does not learn which bucket the user has access to. */ +use super::cred; +use super::IssuerPrivKey; +use super::CMZ_B_TABLE; use aes_gcm::aead; use aes_gcm::aead::{generic_array::GenericArray, Aead, NewAead}; use aes_gcm::Aes128Gcm; +use curve25519_dalek::ristretto::CompressedRistretto; +use curve25519_dalek::ristretto::RistrettoBasepointTable; use curve25519_dalek::scalar::Scalar; use rand::RngCore; +use std::collections::HashSet; use std::convert::TryInto; use subtle::ConstantTimeEq; @@ -22,14 +28,14 @@ pub const BRIDGE_BYTES: usize = 220; /// The max number of bridges per bucket pub const MAX_BRIDGES_PER_BUCKET: usize = 3; -/// The size of a plaintext bucket -pub const BUCKET_BYTES: usize = BRIDGE_BYTES * MAX_BRIDGES_PER_BUCKET; - -/// The size of an encrypted bucket -pub const ENC_BUCKET_BYTES: usize = BUCKET_BYTES + 12 + 16; +/// The minimum number of bridges in a bucket that must be reachable for +/// the bucket to get a Bucket Reachability credential that will allow +/// users of that bucket to gain trust levels (once they are already at +/// level 1) +pub const MIN_BUCKET_REACHABILITY: usize = 2; /// A bridge information line -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] pub struct BridgeLine { /// IPv4 or IPv6 address pub addr: [u8; 16], @@ -40,6 +46,20 @@ pub struct BridgeLine { pub info: [u8; BRIDGE_BYTES - 18], } +/// A bucket contains MAX_BRIDGES_PER_BUCKET bridges plus the +/// information needed to construct a Bucket Reachability credential, +/// which is a 4-byte date, and a (P,Q) MAC +type Bucket = ( + [BridgeLine; MAX_BRIDGES_PER_BUCKET], + Option, +); + +/// The size of a plaintext bucket +pub const BUCKET_BYTES: usize = BRIDGE_BYTES * MAX_BRIDGES_PER_BUCKET + 4 + 32 + 32; + +/// The size of an encrypted bucket +pub const ENC_BUCKET_BYTES: usize = BUCKET_BYTES + 12 + 16; + impl Default for BridgeLine { /// An "empty" BridgeLine is represented by all zeros fn default() -> Self { @@ -68,25 +88,79 @@ impl BridgeLine { res.info.copy_from_slice(&data[18..]); res } - /// Encode a bucket to a byte array - pub fn bucket_encode(bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET]) -> [u8; BUCKET_BYTES] { + /// Encode a bucket to a byte array, including a Bucket Reachability + /// credential if appropriate + pub fn bucket_encode( + bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET], + reachable: &HashSet, + today: u32, + bucket_attr: &Scalar, + reachability_priv: &IssuerPrivKey, + ) -> [u8; BUCKET_BYTES] { let mut res: [u8; BUCKET_BYTES] = [0; BUCKET_BYTES]; let mut pos: usize = 0; + let mut num_reachable: usize = 0; for bridge in bucket { res[pos..pos + BRIDGE_BYTES].copy_from_slice(&bridge.encode()); + if reachable.contains(bridge) { + num_reachable += 1; + } pos += BRIDGE_BYTES; } + if num_reachable >= MIN_BUCKET_REACHABILITY { + // Construct a Bucket Reachability credential for this + // bucket and today's date + let today_attr: Scalar = today.into(); + let mut rng = rand::thread_rng(); + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + let b = Scalar::random(&mut rng); + let P = &b * Btable; + let Q = &(b + * (reachability_priv.x[0] + + reachability_priv.x[1] * today_attr + + reachability_priv.x[2] * bucket_attr)) + * Btable; + res[pos..pos + 4].copy_from_slice(&today.to_le_bytes()); + res[pos + 4..pos + 36].copy_from_slice(&P.compress().as_bytes()[..]); + res[pos + 36..].copy_from_slice(&Q.compress().as_bytes()[..]); + } res } - /// Decode a bucket from a byte array - pub fn bucket_decode(data: &[u8; BUCKET_BYTES]) -> [BridgeLine; MAX_BRIDGES_PER_BUCKET] { + /// Decode a bucket from a byte array, yielding the array of + /// BridgeLine entries and an optional Bucket Reachability + /// credential + fn bucket_decode(data: &[u8; BUCKET_BYTES], bucket_attr: &Scalar) -> Bucket { let mut pos: usize = 0; - let mut res: [BridgeLine; MAX_BRIDGES_PER_BUCKET] = Default::default(); - for bridge in res.iter_mut().take(MAX_BRIDGES_PER_BUCKET) { + let mut bridges: [BridgeLine; MAX_BRIDGES_PER_BUCKET] = Default::default(); + for bridge in bridges.iter_mut().take(MAX_BRIDGES_PER_BUCKET) { *bridge = BridgeLine::decode(data[pos..pos + BRIDGE_BYTES].try_into().unwrap()); pos += BRIDGE_BYTES; } - res + // See if there's a nonzero date in the Bucket Reachability + // Credential + let date = u32::from_le_bytes(data[pos..pos + 4].try_into().unwrap()); + let (optP, optQ) = if date > 0 { + ( + CompressedRistretto::from_slice(&data[pos + 4..pos + 36]).decompress(), + CompressedRistretto::from_slice(&data[pos + 36..]).decompress(), + ) + } else { + (None, None) + }; + if let (Some(P), Some(Q)) = (optP, optQ) { + let date_attr: Scalar = date.into(); + ( + bridges, + Some(cred::BucketReachability { + P, + Q, + date: date_attr, + bucket: *bucket_attr, + }), + ) + } else { + (bridges, None) + } } /// Create a random BridgeLine for testing #[cfg(test)] @@ -134,6 +208,12 @@ pub struct BridgeTable { pub keys: Vec<[u8; 16]>, pub buckets: Vec<[BridgeLine; MAX_BRIDGES_PER_BUCKET]>, pub encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>, + pub reachable: HashSet, + /// The date the buckets were last encrypted to make the encbucket. + /// + /// The encbucket must be rebuilt each day so that the Bucket + /// Reachability credentials in the buckets can be refreshed. + pub date_last_enc: u32, } // Invariant: the lengths of the keys and buckets vectors are the same. @@ -153,18 +233,35 @@ impl BridgeTable { rng.fill_bytes(&mut key); self.keys.push(key); self.buckets.push(bucket); + // Mark the new bridges as available + for b in bucket.iter() { + if b.port > 0 { + self.reachable.insert(*b); + } + } } /// Create the vector of encrypted buckets from the keys and buckets /// 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). - pub fn encrypt_table(&mut self) { + /// Bucket Reachability credentials are added to the buckets when + /// enough (at least MIN_BUCKET_REACHABILITY) bridges in the bucket + /// are reachable. + pub fn encrypt_table(&mut self, today: u32, reachability_priv: &IssuerPrivKey) { let mut rng = rand::thread_rng(); self.encbuckets.clear(); - for (key, bucket) in self.keys.iter().zip(self.buckets.iter()) { + // We want id to be a u32, so we use .zip(0u32..) instead of + // enumerate() + for ((key, bucket), id) in self.keys.iter().zip(self.buckets.iter()).zip(0u32..) { let mut encbucket: [u8; ENC_BUCKET_BYTES] = [0; ENC_BUCKET_BYTES]; - let plainbucket: [u8; BUCKET_BYTES] = BridgeLine::bucket_encode(bucket); + let plainbucket: [u8; BUCKET_BYTES] = BridgeLine::bucket_encode( + bucket, + &self.reachable, + today, + &to_scalar(id, key), + reachability_priv, + ); // Set the AES key let aeskey = GenericArray::from_slice(key); // Pick a random nonce @@ -178,13 +275,16 @@ impl BridgeTable { encbucket[12..].copy_from_slice(ciphertext.as_slice()); self.encbuckets.push(encbucket); } + self.date_last_enc = today; } - /// Decrypt an individual encrypted bucket, given its key + /// Decrypt an individual encrypted bucket, given its id, key, and + /// the encrypted bucket itself pub fn decrypt_bucket( + id: u32, key: &[u8; 16], encbucket: &[u8; ENC_BUCKET_BYTES], - ) -> Result<[BridgeLine; MAX_BRIDGES_PER_BUCKET], aead::Error> { + ) -> Result { // Set the nonce and the key let nonce = GenericArray::from_slice(&encbucket[0..12]); let aeskey = GenericArray::from_slice(key); @@ -194,17 +294,14 @@ impl BridgeTable { // Convert the plaintext bytes to an array of BridgeLines Ok(BridgeLine::bucket_decode( plaintext.as_slice().try_into().unwrap(), + &to_scalar(id, key), )) } /// Decrypt an individual encrypted bucket, given its id and key - pub fn decrypt_bucket_id( - &self, - id: u32, - key: &[u8; 16], - ) -> Result<[BridgeLine; MAX_BRIDGES_PER_BUCKET], aead::Error> { + pub fn decrypt_bucket_id(&self, id: u32, key: &[u8; 16]) -> Result { let encbucket = self.encbuckets[id as usize]; - BridgeTable::decrypt_bucket(key, &encbucket) + BridgeTable::decrypt_bucket(id, key, &encbucket) } } @@ -216,6 +313,8 @@ mod tests { #[test] fn test_bridge_table() -> Result<(), aead::Error> { + // Create private keys for the Bucket Reachability credentials + let reachability_priv = IssuerPrivKey::new(2); // Create an empty bridge table let mut btable: BridgeTable = Default::default(); // Make 20 buckets with one random bridge each @@ -233,8 +332,13 @@ mod tests { ]; btable.new_bucket(bucket); } + let today: u32 = time::OffsetDateTime::now_utc() + .date() + .julian_day() + .try_into() + .unwrap(); // Create the encrypted bridge table - btable.encrypt_table(); + btable.encrypt_table(today, &reachability_priv); // Try to decrypt a 1-bridge bucket let key7 = btable.keys[7]; let bucket7 = btable.decrypt_bucket_id(7, &key7)?; diff --git a/crates/lox-library/src/cred.rs b/crates/lox-library/src/cred.rs index 871f6c6..2d32b4d 100644 --- a/crates/lox-library/src/cred.rs +++ b/crates/lox-library/src/cred.rs @@ -7,9 +7,10 @@ zero-knowledge proof of its correctness (as it does at issuing time). */ use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; -/// 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. +/// 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. #[derive(Debug)] pub struct Migration { pub P: RistrettoPoint, @@ -19,15 +20,17 @@ pub struct Migration { pub to_bucket: Scalar, } -/// 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 Julian date of when this -/// user was changed to the current trust level. (P_noopmigration, -/// Q_noopmigration) are the MAC on the implicit no-op migration -/// credential formed by the attributes (id, bucket, bucket), which -/// authorizes the user to switch from its current bucket to the same -/// bucket (i.e., a no-op). This can be useful for hiding from the BA -/// whether or not the user is performing a bucket 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 +/// Julian date of when this user was changed to the current trust +/// level. (P_noopmigration, Q_noopmigration) are the MAC on the +/// implicit no-op migration credential formed by the attributes (id, +/// bucket, bucket), which authorizes the user to switch from its +/// current bucket to the same bucket (i.e., a no-op). This can be +/// useful for hiding from the BA whether or not the user is performing +/// a bucket migration. #[derive(Debug)] pub struct Lox { pub P: RistrettoPoint, @@ -42,18 +45,40 @@ pub struct Lox { pub Q_noopmigration: RistrettoPoint, } -// The migration key credential is never actually instantiated. It is -// an implicit credential with the following attributes: -// - lox_id: Scalar, -// - from_bucket: Scalar -// Plus the usual (P,Q) MAC. 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 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 credential -// with their new bucket, without the BA learning either their old or -// new buckets. +/// 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 +/// 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 +/// 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 +/// credential with their new bucket, without the BA learning either +/// their old or new buckets. +#[derive(Debug)] +pub struct MigrationKey { + pub P: RistrettoPoint, + pub Q: RistrettoPoint, + pub lox_id: Scalar, + pub from_bucket: Scalar, +} + +/// The Bucket Reachability credential. +/// +/// 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 +/// 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. +#[derive(Debug)] +pub struct BucketReachability { + pub P: RistrettoPoint, + pub Q: RistrettoPoint, + pub date: Scalar, + pub bucket: Scalar, +} diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 8ada29e..043084c 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -186,6 +186,10 @@ pub struct BridgeAuth { migrationkey_priv: IssuerPrivKey, /// The public key for migration key credentials pub migrationkey_pub: IssuerPubKey, + /// The private key for bucket reachability credentials + reachability_priv: IssuerPrivKey, + /// The public key for bucket reachability credentials + pub reachability_pub: IssuerPubKey, /// The public key of the BridgeDb issuing open invitations pub bridgedb_pub: PublicKey, @@ -218,6 +222,8 @@ impl BridgeAuth { let migration_pub = IssuerPubKey::new(&migration_priv); let migrationkey_priv = IssuerPrivKey::new(2); let migrationkey_pub = IssuerPubKey::new(&migrationkey_priv); + let reachability_priv = IssuerPrivKey::new(2); + let reachability_pub = IssuerPubKey::new(&reachability_priv); Self { lox_priv, lox_pub, @@ -225,6 +231,8 @@ impl BridgeAuth { migration_pub, migrationkey_priv, migrationkey_pub, + reachability_priv, + reachability_pub, bridgedb_pub, bridge_table: Default::default(), migration_table: Default::default(), @@ -258,6 +266,20 @@ impl BridgeAuth { .unwrap() } + /// Get a reference to the encrypted bridge table. + /// + /// Be sure to call this function when you want the latest version + /// of the table, since it will put fresh Bucket Reachability + /// credentials in the buckets each day. + pub fn enc_bridge_table(&mut self) -> &Vec<[u8; bridge_table::ENC_BUCKET_BYTES]> { + let today = self.today(); + if self.bridge_table.date_last_enc != today { + self.bridge_table + .encrypt_table(today, &self.reachability_priv); + } + &self.bridge_table.encbuckets + } + #[cfg(test)] /// Verify the two MACs on a Lox credential pub fn verify_lox(&self, cred: &cred::Lox) -> bool { @@ -297,6 +319,20 @@ impl BridgeAuth { * cred.P; return Q == cred.Q; } + + #[cfg(test)] + /// Verify the MAC on a Bucket Reachability credential + pub fn verify_reachability(&self, cred: &cred::BucketReachability) -> bool { + if cred.P.is_identity() { + return false; + } + + let Q = (self.reachability_priv.x[0] + + cred.date * self.reachability_priv.x[1] + + cred.bucket * self.reachability_priv.x[2]) + * cred.P; + return Q == cred.Q; + } } /// Try to extract a u64 from a Scalar diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index aec5c37..9a43f68 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -28,7 +28,7 @@ fn test_open_invite() { ba.bridge_table.new_bucket(bucket); } // Create the encrypted bridge table - ba.bridge_table.encrypt_table(); + ba.enc_bridge_table(); // Issue an open invitation let inv = bdb.invite(); @@ -40,7 +40,9 @@ fn test_open_invite() { // Check that we can use the credential to read a bucket let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); - let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap(); + let encbuckets = ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("cred = {:?}", cred); println!("bucket = {:?}", bucket); assert!(ba.verify_lox(&cred)); @@ -74,7 +76,7 @@ fn setup() -> (BridgeDb, BridgeAuth) { ba.migration_table.table.insert(3 * i + 2, 15 + i); } // Create the encrypted bridge table - ba.bridge_table.encrypt_table(); + ba.enc_bridge_table(); (bdb, ba) } @@ -109,7 +111,9 @@ fn test_trust_promotion() { // Check that we can use the to_bucket in the Migration credenital // to read a bucket let (id, key) = bridge_table::from_scalar(migcred.to_bucket).unwrap(); - let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap(); + let encbuckets = ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("bucket = {:?}", bucket); } @@ -128,6 +132,8 @@ fn test_level0_migration() { println!("newloxcred = {:?}", newloxcred); // Check that we can use the credenital to read a bucket let (id, key) = bridge_table::from_scalar(newloxcred.bucket).unwrap(); - let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap(); + let encbuckets = ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("bucket = {:?}", bucket); } From 5bfbccf1931c6822b772c919239937b9ed238d4d Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Sat, 1 May 2021 17:19:34 -0400 Subject: [PATCH 028/115] Check the MACs on the Bucket Reachability credentials in the tests --- crates/lox-library/src/tests.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 9a43f68..eeef6d3 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -45,6 +45,7 @@ fn test_open_invite() { bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("cred = {:?}", cred); println!("bucket = {:?}", bucket); + assert!(bucket.1.is_none()); assert!(ba.verify_lox(&cred)); } @@ -115,6 +116,7 @@ fn test_trust_promotion() { let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("bucket = {:?}", bucket); + assert!(ba.verify_reachability(&bucket.1.unwrap())); } #[test] @@ -136,4 +138,5 @@ fn test_level0_migration() { let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("bucket = {:?}", bucket); + assert!(ba.verify_reachability(&bucket.1.unwrap())); } From f7b3d242bb6c2a83e43a67ec35d685cf01229e5b Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Sat, 1 May 2021 22:25:32 -0400 Subject: [PATCH 029/115] The request message of the level upgrade protocol --- crates/lox-library/src/lib.rs | 1 + crates/lox-library/src/proto/level_up.rs | 579 +++++++++++++++++++++++ crates/lox-library/src/tests.rs | 39 +- 3 files changed, 614 insertions(+), 5 deletions(-) create mode 100644 crates/lox-library/src/proto/level_up.rs diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 043084c..37338a8 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -376,6 +376,7 @@ pub fn pt_dbl(P: &RistrettoPoint) -> RistrettoPoint { /// Response. It also adds a handle_* function to the BridgeAuth struct /// that consumes a Request and produces a Result. pub mod proto { + pub mod level_up; pub mod migration; pub mod open_invite; pub mod trust_promotion; diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs new file mode 100644 index 0000000..4edd7d8 --- /dev/null +++ b/crates/lox-library/src/proto/level_up.rs @@ -0,0 +1,579 @@ +/*! A module for the protocol for the user to increase their trust level +(from a level at least 1; use the trust promotion protocol to go from +untrusted (level 0) to minimally trusted (level 1). + +They are allowed to do this as long as some amount of time (depending on +their current level) has elapsed since their last level change, and they +have a Bucket Reachability credential for their current bucket and +today's date. (Such credentials are placed daily in the encrypted +bridge table.) + +The user presents their current Lox credential: +- id: revealed +- bucket: blinded +- trust_level: revealed, and must be at least 1 +- level_since: blinded, but proved in ZK that it's at least the + appropriate number of days ago +- invites_remaining: blinded +- invites_issued: blinded + +and a Bucket Reachability credential: +- date: revealed to be today +- bucket: blinded, but proved in ZK that it's the same as in the Lox + credential above + +and a new Lox credential to be issued: + +- id: jointly chosen by the user and BA +- bucket: blinded, but proved in ZK that it's the same as in the Lox + credential above +- trust_level: revealed to be one more than the trust level above +- level_since: today +- invites_remaining: blinded, but proved in ZK that it's the same as in + the Lox credential above, _plus_ a per-level constant +- invites_issued: blinded, but proved in ZK that it's the same as in the + Lox credential above + +*/ + +use curve25519_dalek::ristretto::RistrettoBasepointTable; +use curve25519_dalek::ristretto::RistrettoPoint; +use curve25519_dalek::scalar::Scalar; +use curve25519_dalek::traits::IsIdentity; + +use zkp::CompactProof; +use zkp::ProofError; +use zkp::Transcript; + +use super::super::cred; +use super::super::dup_filter::SeenType; +use super::super::{pt_dbl, scalar_dbl, scalar_u32}; +use super::super::{BridgeAuth, IssuerPubKey}; +use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; + +/// LEVEL_INTERVAL\[i\] for i >= 1 is the minimum number of days a user +/// must be at trust level i before advancing to level i+1. The large +/// last entry makes it impossible to advance past the top level. Note +/// that the LEVEL_INTERVAL\[0\] entry is a dummy; the trust_promotion +/// protocol is used instead of this one to move from level 0 to level +/// 1. +pub const LEVEL_INTERVAL: [u32; 5] = [0, 14, 28, 56, u32::MAX]; + +/// LEVEL_INVITATIONS\[i\] for i >= 1 is the number of additional +/// invitations a user will be eligible to issue upon advancing from +/// level i to level i+1. Again the LEVEL_INVITATIONS\[0\] entry is a +/// dummy, as for LEVEL_INTERVAL. Also the last entry is 0 because +/// users cannot advance above the highest level. +pub const LEVEL_INVITATIONS: [u32; 5] = [0, 2, 4, 6, 0]; + +pub struct Request { + // Fields for blind showing the Lox credential + P: RistrettoPoint, + id: Scalar, + CBucket: RistrettoPoint, + level: Scalar, + CSince: RistrettoPoint, + CInvRemain: RistrettoPoint, + CInvIssued: RistrettoPoint, + CQ: RistrettoPoint, + + // Fields for blind showing the Bucket Reachability credential + P_reach: RistrettoPoint, + CBucket_reach: RistrettoPoint, + CQ_reach: RistrettoPoint, + + // Fields for the inequality proof (level_since + + // LEVEL_INTERVAL[level] <= today) + CG1: RistrettoPoint, + CG2: RistrettoPoint, + CG3: RistrettoPoint, + CG4: RistrettoPoint, + CG5: RistrettoPoint, + CG6: RistrettoPoint, + CG7: RistrettoPoint, + CG8: RistrettoPoint, + CG0sq: RistrettoPoint, + CG1sq: RistrettoPoint, + CG2sq: RistrettoPoint, + CG3sq: RistrettoPoint, + CG4sq: RistrettoPoint, + CG5sq: RistrettoPoint, + CG6sq: RistrettoPoint, + CG7sq: RistrettoPoint, + CG8sq: RistrettoPoint, + + // Fields for user blinding of the Lox credential to be issued + D: RistrettoPoint, + EncIdClient: (RistrettoPoint, RistrettoPoint), + EncBucket: (RistrettoPoint, RistrettoPoint), + EncInvRemain: (RistrettoPoint, RistrettoPoint), + EncInvIssued: (RistrettoPoint, RistrettoPoint), + + // The combined ZKP + piUser: CompactProof, +} + +#[derive(Debug)] +pub struct State { + d: Scalar, + D: RistrettoPoint, + EncIdClient: (RistrettoPoint, RistrettoPoint), + EncBucket: (RistrettoPoint, RistrettoPoint), + EncInvRemain: (RistrettoPoint, RistrettoPoint), + EncInvIssued: (RistrettoPoint, RistrettoPoint), + id_client: Scalar, + bucket: Scalar, + level: Scalar, + invremain: Scalar, + invissued: Scalar, +} + +pub struct Response { + // The fields for the new Lox credential; the new trust level is one + // more than the old trust level, so we don't have to include it + // here explicitly + P: RistrettoPoint, + EncQ: (RistrettoPoint, RistrettoPoint), + id_server: Scalar, + level_since: Scalar, + TId: RistrettoPoint, + TBucket: RistrettoPoint, + TInvRemain: RistrettoPoint, + TInvIssued: RistrettoPoint, + + // The fields for the implicit noop migration ("nm") credential + P_nm: RistrettoPoint, + EncQ_nm: (RistrettoPoint, RistrettoPoint), + TId_nm: RistrettoPoint, + TBucket_nm: RistrettoPoint, + + // The ZKP + piBlindIssue: CompactProof, +} + +define_proof! { + requestproof, + "Level Upgrade Request", + (bucket, since, invremain, invissued, zbucket, zsince, zinvremain, + zinvissued, negzQ, + zbucket_reach, negzQ_reach, + d, eid_client, ebucket, einvremain, einvissued, id_client, + g0, g1, g2, g3, g4, g5, g6, g7, g8, + zg0, zg1, zg2, zg3, zg4, zg5, zg6, zg7, zg8, + wg0, wg1, wg2, wg3, wg4, wg5, wg6, wg7, wg8, + yg0, yg1, yg2, yg3, yg4, yg5, yg6, yg7, yg8), + (P, CBucket, CSince, CInvRemain, CInvIssued, V, Xbucket, Xsince, + Xinvremain, Xinvissued, + P_reach, CBucket_reach, V_reach, Xbucket_reach, + D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1, + EncInvRemain0, EncInvRemain1_minus_LEVELINV_B, + EncInvIssued0, EncInvIssued1, + CG0, CG1, CG2, CG3, CG4, CG5, CG6, CG7, CG8, + CG0sq, CG1sq, CG2sq, CG3sq, CG4sq, CG5sq, CG6sq, CG7sq, CG8sq), + (A, B) : + // Blind showing of the Lox credential + CBucket = (bucket*P + zbucket*A), + CSince = (since*P + zsince*A), + CInvRemain = (invremain*P + zinvremain*A), + CInvIssued = (invissued*P + zinvissued*A), + // Blind showing of the Bucket Reachability credential; note the + // same bucket is used in the proof + CBucket_reach = (bucket*P_reach + zbucket_reach*A), + // User blinding of the Lox credential to be issued + D = (d*B), + EncIdClient0 = (eid_client*B), + EncIdClient1 = (id_client*B + eid_client*D), + EncBucket0 = (ebucket*B), + EncBucket1 = (bucket*B + ebucket*D), + EncInvRemain0 = (einvremain*B), + EncInvRemain1_minus_LEVELINV_B = (invremain*B + einvremain*D), + EncInvIssued0 = (einvissued*B), + EncInvIssued1 = (invissued*B + einvissued*D), + // Prove CSince encodes a value at least LEVEL_INTERVAL + // days ago (at technically at most LEVEL_INTERVAL+511 days + // ago): first prove each of g0, ..., g8 is a bit by proving that + // gi = gi^2 + CG0 = (g0*P + zg0*A), CG0sq = (g0*CG0 + wg0*A), CG0sq = (g0*P + yg0*A), + CG1 = (g1*P + zg1*A), CG1sq = (g1*CG1 + wg1*A), CG1sq = (g1*P + yg1*A), + CG2 = (g2*P + zg2*A), CG2sq = (g2*CG2 + wg2*A), CG2sq = (g2*P + yg2*A), + CG3 = (g3*P + zg3*A), CG3sq = (g3*CG3 + wg3*A), CG3sq = (g3*P + yg3*A), + CG4 = (g4*P + zg4*A), CG4sq = (g4*CG4 + wg4*A), CG4sq = (g4*P + yg4*A), + CG5 = (g5*P + zg5*A), CG5sq = (g5*CG5 + wg5*A), CG5sq = (g5*P + yg5*A), + CG6 = (g6*P + zg6*A), CG6sq = (g6*CG6 + wg6*A), CG6sq = (g6*P + yg6*A), + CG7 = (g7*P + zg7*A), CG7sq = (g7*CG7 + wg7*A), CG7sq = (g7*P + yg7*A), + CG8 = (g8*P + zg8*A), CG8sq = (g8*CG8 + wg8*A), CG8sq = (g8*P + yg8*A) + // Then we'll check that CSince + LEVEL_INTERVAL*P + CG0 + 2*CG1 + // + 4*CG2 + 8*CG3 + ... + 256*CG8 = today*P by having the verifier + // plug in today*P - (CSince + LEVEL_INTERVAL*P + 2*CG1 + 4*CG2 + // + ... + 256*CG8) as its value of CG0. +} + +pub fn request( + lox_cred: &cred::Lox, + reach_cred: &cred::BucketReachability, + lox_pub: &IssuerPubKey, + reach_pub: &IssuerPubKey, + today: u32, +) -> Result<(Request, State), ProofError> { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + // Ensure the credential can be correctly shown: it must be the case + // that level_since + LEVEL_INTERVAL[level] <= today. + let level_since: u32 = match scalar_u32(&lox_cred.level_since) { + Some(v) => v, + None => return Err(ProofError::VerificationFailure), + }; + // The trust level has to be at least 1 + let trust_level: u32 = match scalar_u32(&lox_cred.trust_level) { + Some(v) => v, + None => return Err(ProofError::VerificationFailure), + }; + if trust_level < 1 { + return Err(ProofError::VerificationFailure); + } + // The trust level has to be no higher than the highest level + let level_interval: u32 = match LEVEL_INTERVAL.get(trust_level as usize) { + Some(&v) => v, + None => return Err(ProofError::VerificationFailure), + }; + if level_since + level_interval > today { + return Err(ProofError::VerificationFailure); + } + // The credential can't be _too_ old + let diffdays = today - (level_since + level_interval); + if diffdays > 511 { + return Err(ProofError::VerificationFailure); + } + // The buckets in the Lox and Bucket Reachability credentials have + // to match + if lox_cred.bucket != reach_cred.bucket { + return Err(ProofError::VerificationFailure); + } + // The Bucket Reachability credential has to be dated today + let reach_date: u32 = match scalar_u32(&reach_cred.date) { + Some(v) => v, + None => return Err(ProofError::VerificationFailure), + }; + if reach_date != today { + return Err(ProofError::VerificationFailure); + } + + // Blind showing the Lox credential + + // Reblind P and Q + let mut rng = rand::thread_rng(); + let t = Scalar::random(&mut rng); + let P = t * lox_cred.P; + let Q = t * lox_cred.Q; + + // Form Pedersen commitments to the blinded attributes + let zbucket = Scalar::random(&mut rng); + let zsince = Scalar::random(&mut rng); + let zinvremain = Scalar::random(&mut rng); + let zinvissued = Scalar::random(&mut rng); + let CBucket = lox_cred.bucket * P + &zbucket * Atable; + let CSince = lox_cred.level_since * P + &zsince * Atable; + let CInvRemain = lox_cred.invites_remaining * P + &zinvremain * Atable; + let CInvIssued = lox_cred.invites_issued * P + &zinvissued * Atable; + + // Form a Pedersen commitment to the MAC Q + // We flip the sign of zQ from that of the Hyphae paper so that + // the ZKP has a "+" instead of a "-", as that's what the zkp + // macro supports. + let negzQ = Scalar::random(&mut rng); + let CQ = Q - &negzQ * Atable; + + // Compute the "error factor" + let V = zbucket * lox_pub.X[2] + + zsince * lox_pub.X[4] + + zinvremain * lox_pub.X[5] + + zinvissued * lox_pub.X[6] + + &negzQ * Atable; + + // Blind showing the Bucket Reachability credential + + // Reblind P and Q + let t_reach = Scalar::random(&mut rng); + let P_reach = t_reach * reach_cred.P; + let Q_reach = t_reach * reach_cred.Q; + + // Form Pedersen commitments to the blinded attributes + let zbucket_reach = Scalar::random(&mut rng); + let CBucket_reach = reach_cred.bucket * P_reach + &zbucket_reach * Atable; + + // Form a Pedersen commitment to the MAC Q + // We flip the sign of zQ from that of the Hyphae paper so that + // the ZKP has a "+" instead of a "-", as that's what the zkp + // macro supports. + let negzQ_reach = Scalar::random(&mut rng); + let CQ_reach = Q_reach - &negzQ_reach * Atable; + + // Compute the "error factor" + let V_reach = zbucket_reach * reach_pub.X[2] + &negzQ_reach * Atable; + + // User blinding for the Lox certificate to be issued + + // Pick an ElGamal keypair + let d = Scalar::random(&mut rng); + let D = &d * Btable; + + // Pick a random client component of the id + let id_client = Scalar::random(&mut rng); + + // Encrypt it (times the basepoint B) to the ElGamal public key D we + // just created + let eid_client = Scalar::random(&mut rng); + let EncIdClient = (&eid_client * Btable, &id_client * Btable + eid_client * D); + + // Encrypt the other blinded fields (times B) to D as well + let ebucket = Scalar::random(&mut rng); + let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D); + let newinvites: Scalar = LEVEL_INVITATIONS[trust_level as usize].into(); + let einvremain = Scalar::random(&mut rng); + let EncInvRemain = ( + &einvremain * Btable, + &(lox_cred.invites_remaining + newinvites) * Btable + einvremain * D, + ); + let einvissued = Scalar::random(&mut rng); + let EncInvIssued = ( + &einvissued * Btable, + &lox_cred.invites_issued * Btable + einvissued * D, + ); + + // The range proof that 0 <= diffdays <= 511 + + // Extract the 9 bits from diffdays + let g0: Scalar = (diffdays & 1).into(); + let g1: Scalar = ((diffdays >> 1) & 1).into(); + let g2: Scalar = ((diffdays >> 2) & 1).into(); + let g3: Scalar = ((diffdays >> 3) & 1).into(); + let g4: Scalar = ((diffdays >> 4) & 1).into(); + let g5: Scalar = ((diffdays >> 5) & 1).into(); + let g6: Scalar = ((diffdays >> 6) & 1).into(); + let g7: Scalar = ((diffdays >> 7) & 1).into(); + let g8: Scalar = ((diffdays >> 8) & 1).into(); + + // Pick random factors for the Pedersen commitments + let wg0 = Scalar::random(&mut rng); + let zg1 = Scalar::random(&mut rng); + let wg1 = Scalar::random(&mut rng); + let zg2 = Scalar::random(&mut rng); + let wg2 = Scalar::random(&mut rng); + let zg3 = Scalar::random(&mut rng); + let wg3 = Scalar::random(&mut rng); + let zg4 = Scalar::random(&mut rng); + let wg4 = Scalar::random(&mut rng); + let zg5 = Scalar::random(&mut rng); + let wg5 = Scalar::random(&mut rng); + let zg6 = Scalar::random(&mut rng); + let wg6 = Scalar::random(&mut rng); + let zg7 = Scalar::random(&mut rng); + let wg7 = Scalar::random(&mut rng); + let zg8 = Scalar::random(&mut rng); + let wg8 = Scalar::random(&mut rng); + + // Compute zg0 to cancel things out as + // zg0 = -(zsince + 2*zg1 + 4*zg2 + 8*zg3 + 16*zg4 + 32*zg5 + 64*zg6 + 128*zg7 + 256*zg8) + // but use Horner's method + let zg0 = -(scalar_dbl( + &(scalar_dbl( + &(scalar_dbl( + &(scalar_dbl( + &(scalar_dbl( + &(scalar_dbl(&(scalar_dbl(&(scalar_dbl(&zg8) + zg7)) + zg6)) + zg5), + ) + zg4), + ) + zg3), + ) + zg2), + ) + zg1), + ) + zsince); + + let yg0 = wg0 + g0 * zg0; + let yg1 = wg1 + g1 * zg1; + let yg2 = wg2 + g2 * zg2; + let yg3 = wg3 + g3 * zg3; + let yg4 = wg4 + g4 * zg4; + let yg5 = wg5 + g5 * zg5; + let yg6 = wg6 + g6 * zg6; + let yg7 = wg7 + g7 * zg7; + let yg8 = wg8 + g8 * zg8; + + let CG0 = g0 * P + &zg0 * Atable; + let CG1 = g1 * P + &zg1 * Atable; + let CG2 = g2 * P + &zg2 * Atable; + let CG3 = g3 * P + &zg3 * Atable; + let CG4 = g4 * P + &zg4 * Atable; + let CG5 = g5 * P + &zg5 * Atable; + let CG6 = g6 * P + &zg6 * Atable; + let CG7 = g7 * P + &zg7 * Atable; + let CG8 = g8 * P + &zg8 * Atable; + + let CG0sq = g0 * P + &yg0 * Atable; + let CG1sq = g1 * P + &yg1 * Atable; + let CG2sq = g2 * P + &yg2 * Atable; + let CG3sq = g3 * P + &yg3 * Atable; + let CG4sq = g4 * P + &yg4 * Atable; + let CG5sq = g5 * P + &yg5 * Atable; + let CG6sq = g6 * P + &yg6 * Atable; + let CG7sq = g7 * P + &yg7 * Atable; + let CG8sq = g8 * P + &yg8 * Atable; + + // Construct the proof + let mut transcript = Transcript::new(b"level upgrade request"); + let piUser = requestproof::prove_compact( + &mut transcript, + requestproof::ProveAssignments { + A: &A, + B: &B, + P: &P, + CBucket: &CBucket, + CSince: &CSince, + CInvRemain: &CInvRemain, + CInvIssued: &CInvIssued, + V: &V, + Xbucket: &lox_pub.X[2], + Xsince: &lox_pub.X[4], + Xinvremain: &lox_pub.X[5], + Xinvissued: &lox_pub.X[6], + P_reach: &P_reach, + CBucket_reach: &CBucket_reach, + V_reach: &V_reach, + Xbucket_reach: &reach_pub.X[2], + D: &D, + EncIdClient0: &EncIdClient.0, + EncIdClient1: &EncIdClient.1, + EncBucket0: &EncBucket.0, + EncBucket1: &EncBucket.1, + EncInvRemain0: &EncInvRemain.0, + EncInvRemain1_minus_LEVELINV_B: &(EncInvRemain.1 - &newinvites * Btable), + EncInvIssued0: &EncInvIssued.0, + EncInvIssued1: &EncInvIssued.1, + CG0: &CG0, + CG1: &CG1, + CG2: &CG2, + CG3: &CG3, + CG4: &CG4, + CG5: &CG5, + CG6: &CG6, + CG7: &CG7, + CG8: &CG8, + CG0sq: &CG0sq, + CG1sq: &CG1sq, + CG2sq: &CG2sq, + CG3sq: &CG3sq, + CG4sq: &CG4sq, + CG5sq: &CG5sq, + CG6sq: &CG6sq, + CG7sq: &CG7sq, + CG8sq: &CG8sq, + bucket: &lox_cred.bucket, + since: &lox_cred.level_since, + invremain: &lox_cred.invites_remaining, + invissued: &lox_cred.invites_issued, + zbucket: &zbucket, + zsince: &zsince, + zinvremain: &zinvremain, + zinvissued: &zinvissued, + negzQ: &negzQ, + zbucket_reach: &zbucket_reach, + negzQ_reach: &negzQ_reach, + d: &d, + eid_client: &eid_client, + ebucket: &ebucket, + einvremain: &einvremain, + einvissued: &einvissued, + id_client: &id_client, + g0: &g0, + g1: &g1, + g2: &g2, + g3: &g3, + g4: &g4, + g5: &g5, + g6: &g6, + g7: &g7, + g8: &g8, + zg0: &zg0, + zg1: &zg1, + zg2: &zg2, + zg3: &zg3, + zg4: &zg4, + zg5: &zg5, + zg6: &zg6, + zg7: &zg7, + zg8: &zg8, + wg0: &wg0, + wg1: &wg1, + wg2: &wg2, + wg3: &wg3, + wg4: &wg4, + wg5: &wg5, + wg6: &wg6, + wg7: &wg7, + wg8: &wg8, + yg0: &yg0, + yg1: &yg1, + yg2: &yg2, + yg3: &yg3, + yg4: &yg4, + yg5: &yg5, + yg6: &yg6, + yg7: &yg7, + yg8: &yg8, + }, + ) + .0; + + Ok(( + Request { + P, + id: lox_cred.id, + CBucket, + level: lox_cred.trust_level, + CSince, + CInvRemain, + CInvIssued, + CQ, + P_reach, + CBucket_reach, + CQ_reach, + D, + EncIdClient, + EncBucket, + EncInvRemain, + EncInvIssued, + CG1, + CG2, + CG3, + CG4, + CG5, + CG6, + CG7, + CG8, + CG0sq, + CG1sq, + CG2sq, + CG3sq, + CG4sq, + CG5sq, + CG6sq, + CG7sq, + CG8sq, + piUser, + }, + State { + d, + D, + EncIdClient, + EncBucket, + EncInvRemain, + EncInvIssued, + id_client, + bucket: lox_cred.bucket, + level: lox_cred.trust_level + Scalar::one(), + invremain: lox_cred.invites_remaining + newinvites, + invissued: lox_cred.invites_issued, + }, + )) +} diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index eeef6d3..bb40cda 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -119,17 +119,23 @@ fn test_trust_promotion() { assert!(ba.verify_reachability(&bucket.1.unwrap())); } -#[test] -fn test_level0_migration() { - let (bdb, mut ba) = setup(); - - let (loxcred, migcred) = trust_promotion(&bdb, &mut ba); +fn level0_migration(bdb: &BridgeDb, ba: &mut BridgeAuth) -> cred::Lox { + let (loxcred, migcred) = trust_promotion(bdb, ba); let (migreq, migstate) = migration::request(&loxcred, &migcred, &ba.lox_pub, &ba.migration_pub).unwrap(); let migresp = ba.handle_migration(migreq).unwrap(); let newloxcred = migration::handle_response(migstate, migresp, &ba.lox_pub, &ba.migration_pub).unwrap(); + newloxcred +} + +#[test] +fn test_level0_migration() { + let (bdb, mut ba) = setup(); + + let newloxcred = level0_migration(&bdb, &mut ba); + assert!(ba.verify_lox(&newloxcred)); println!("newloxcred = {:?}", newloxcred); // Check that we can use the credenital to read a bucket @@ -140,3 +146,26 @@ fn test_level0_migration() { println!("bucket = {:?}", bucket); assert!(ba.verify_reachability(&bucket.1.unwrap())); } + +#[test] +fn test_level_up() { + let (bdb, mut ba) = setup(); + let loxcred = level0_migration(&bdb, &mut ba); + + // Time passes + ba.advance_days(20); + + let (id, key) = bridge_table::from_scalar(loxcred.bucket).unwrap(); + let encbuckets = ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); + let reachcred = bucket.1.unwrap(); + let (req, state) = level_up::request( + &loxcred, + &reachcred, + &ba.lox_pub, + &ba.reachability_pub, + ba.today(), + ) + .unwrap(); +} From aa097dc4476d1e683a95fcf0e022ee81eabbf4ca Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Sun, 2 May 2021 18:10:59 -0400 Subject: [PATCH 030/115] Change the policy for invites_remaining in the level up protocol Before, the number of invitations at the new level were _added_ to a user's credential. Now, it _replaces_ the old value. --- crates/lox-library/src/proto/level_up.rs | 54 ++++++++++-------------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs index 4edd7d8..f97da18 100644 --- a/crates/lox-library/src/proto/level_up.rs +++ b/crates/lox-library/src/proto/level_up.rs @@ -29,8 +29,9 @@ and a new Lox credential to be issued: credential above - trust_level: revealed to be one more than the trust level above - level_since: today -- invites_remaining: blinded, but proved in ZK that it's the same as in - the Lox credential above, _plus_ a per-level constant +- invites_remaining: revealed to be the number of invites for the new + level (note that the invites_remaining from the previous credential + are _not_ carried over) - invites_issued: blinded, but proved in ZK that it's the same as in the Lox credential above @@ -51,20 +52,24 @@ use super::super::{pt_dbl, scalar_dbl, scalar_u32}; use super::super::{BridgeAuth, IssuerPubKey}; use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; -/// LEVEL_INTERVAL\[i\] for i >= 1 is the minimum number of days a user -/// must be at trust level i before advancing to level i+1. The large -/// last entry makes it impossible to advance past the top level. Note -/// that the LEVEL_INTERVAL\[0\] entry is a dummy; the trust_promotion -/// protocol is used instead of this one to move from level 0 to level -/// 1. -pub const LEVEL_INTERVAL: [u32; 5] = [0, 14, 28, 56, u32::MAX]; +/// The maximum trust level in the system. A user can run this level +/// upgrade protocol when they're already at the max level; they will +/// get a fresh invites_remaining batch, and reset their level_since +/// field to today's date, but will remain in the max level. +pub const MAX_LEVEL: usize = 3; -/// LEVEL_INVITATIONS\[i\] for i >= 1 is the number of additional -/// invitations a user will be eligible to issue upon advancing from -/// level i to level i+1. Again the LEVEL_INVITATIONS\[0\] entry is a -/// dummy, as for LEVEL_INTERVAL. Also the last entry is 0 because -/// users cannot advance above the highest level. -pub const LEVEL_INVITATIONS: [u32; 5] = [0, 2, 4, 6, 0]; +/// LEVEL_INTERVAL\[i\] for i >= 1 is the minimum number of days a user +/// must be at trust level i before advancing to level i+1 (or as above, +/// remain at level i if i == MAX_LEVEL). Note that the +/// LEVEL_INTERVAL\[0\] entry is a dummy; the trust_promotion protocol +/// is used instead of this one to move from level 0 to level 1. +pub const LEVEL_INTERVAL: [u32; MAX_LEVEL + 1] = [0, 14, 28, 56]; + +/// LEVEL_INVITATIONS\[i\] for i >= 1 is the number of invitations a +/// user will be eligible to issue upon advancing from level i to level +/// i+1. Again the LEVEL_INVITATIONS\[0\] entry is a dummy, as for +/// LEVEL_INTERVAL. +pub const LEVEL_INVITATIONS: [u32; MAX_LEVEL + 1] = [0, 2, 4, 6]; pub struct Request { // Fields for blind showing the Lox credential @@ -106,7 +111,6 @@ pub struct Request { D: RistrettoPoint, EncIdClient: (RistrettoPoint, RistrettoPoint), EncBucket: (RistrettoPoint, RistrettoPoint), - EncInvRemain: (RistrettoPoint, RistrettoPoint), EncInvIssued: (RistrettoPoint, RistrettoPoint), // The combined ZKP @@ -119,7 +123,6 @@ pub struct State { D: RistrettoPoint, EncIdClient: (RistrettoPoint, RistrettoPoint), EncBucket: (RistrettoPoint, RistrettoPoint), - EncInvRemain: (RistrettoPoint, RistrettoPoint), EncInvIssued: (RistrettoPoint, RistrettoPoint), id_client: Scalar, bucket: Scalar, @@ -157,7 +160,7 @@ define_proof! { (bucket, since, invremain, invissued, zbucket, zsince, zinvremain, zinvissued, negzQ, zbucket_reach, negzQ_reach, - d, eid_client, ebucket, einvremain, einvissued, id_client, + d, eid_client, ebucket, einvissued, id_client, g0, g1, g2, g3, g4, g5, g6, g7, g8, zg0, zg1, zg2, zg3, zg4, zg5, zg6, zg7, zg8, wg0, wg1, wg2, wg3, wg4, wg5, wg6, wg7, wg8, @@ -166,7 +169,6 @@ define_proof! { Xinvremain, Xinvissued, P_reach, CBucket_reach, V_reach, Xbucket_reach, D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1, - EncInvRemain0, EncInvRemain1_minus_LEVELINV_B, EncInvIssued0, EncInvIssued1, CG0, CG1, CG2, CG3, CG4, CG5, CG6, CG7, CG8, CG0sq, CG1sq, CG2sq, CG3sq, CG4sq, CG5sq, CG6sq, CG7sq, CG8sq), @@ -185,8 +187,6 @@ define_proof! { EncIdClient1 = (id_client*B + eid_client*D), EncBucket0 = (ebucket*B), EncBucket1 = (bucket*B + ebucket*D), - EncInvRemain0 = (einvremain*B), - EncInvRemain1_minus_LEVELINV_B = (invremain*B + einvremain*D), EncInvIssued0 = (einvissued*B), EncInvIssued1 = (invissued*B + einvissued*D), // Prove CSince encodes a value at least LEVEL_INTERVAL @@ -332,11 +332,6 @@ pub fn request( let ebucket = Scalar::random(&mut rng); let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D); let newinvites: Scalar = LEVEL_INVITATIONS[trust_level as usize].into(); - let einvremain = Scalar::random(&mut rng); - let EncInvRemain = ( - &einvremain * Btable, - &(lox_cred.invites_remaining + newinvites) * Btable + einvremain * D, - ); let einvissued = Scalar::random(&mut rng); let EncInvIssued = ( &einvissued * Btable, @@ -446,8 +441,6 @@ pub fn request( EncIdClient1: &EncIdClient.1, EncBucket0: &EncBucket.0, EncBucket1: &EncBucket.1, - EncInvRemain0: &EncInvRemain.0, - EncInvRemain1_minus_LEVELINV_B: &(EncInvRemain.1 - &newinvites * Btable), EncInvIssued0: &EncInvIssued.0, EncInvIssued1: &EncInvIssued.1, CG0: &CG0, @@ -482,7 +475,6 @@ pub fn request( d: &d, eid_client: &eid_client, ebucket: &ebucket, - einvremain: &einvremain, einvissued: &einvissued, id_client: &id_client, g0: &g0, @@ -541,7 +533,6 @@ pub fn request( D, EncIdClient, EncBucket, - EncInvRemain, EncInvIssued, CG1, CG2, @@ -567,12 +558,11 @@ pub fn request( D, EncIdClient, EncBucket, - EncInvRemain, EncInvIssued, id_client, bucket: lox_cred.bucket, level: lox_cred.trust_level + Scalar::one(), - invremain: lox_cred.invites_remaining + newinvites, + invremain: newinvites, invissued: lox_cred.invites_issued, }, )) From fd73286e78b94d0294f0971b1e81e463f962fffd Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Sun, 2 May 2021 21:44:33 -0400 Subject: [PATCH 031/115] Complete the level upgrade protocol --- crates/lox-library/src/proto/level_up.rs | 414 +++++++++++++++++- crates/lox-library/src/proto/migration.rs | 2 +- .../lox-library/src/proto/trust_promotion.rs | 2 +- crates/lox-library/src/tests.rs | 52 ++- 4 files changed, 454 insertions(+), 16 deletions(-) diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs index f97da18..faf4cdc 100644 --- a/crates/lox-library/src/proto/level_up.rs +++ b/crates/lox-library/src/proto/level_up.rs @@ -141,7 +141,6 @@ pub struct Response { level_since: Scalar, TId: RistrettoPoint, TBucket: RistrettoPoint, - TInvRemain: RistrettoPoint, TInvIssued: RistrettoPoint, // The fields for the implicit noop migration ("nm") credential @@ -208,6 +207,50 @@ define_proof! { // + ... + 256*CG8) as its value of CG0. } +define_proof! { + blindissue, + "Level Upgrade Issuing", + (x0, x0tilde, xid, xbucket, xlevel, xsince, xinvremain, xinvissued, + s, b, tid, tbucket, tinvissued, + x0_nm, x0tilde_nm, xid_nm, xfrom_nm, xto_nm, s_nm, b_nm, tid_nm, tbucket_nm), + (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xlevel, Xsince, Xinvremain, + Xinvissued, Plevel, Psince, Pinvremain, TId, TBucket, TInvIssued, + P_nm, EncQ0_nm, EncQ1_nm, X0_nm, Xid_nm, Xfrom_nm, Xto_nm, + TId_nm, TBucket_nm, + D, EncId0, EncId1, EncBucket0, EncBucket1, EncInvIssued0, EncInvIssued1), + (A, B): + Xid = (xid*A), + Xid = (xid*A), + Xlevel = (xlevel*A), + Xbucket = (xbucket*A), + Xsince = (xsince*A), + Xinvremain = (xinvremain*A), + Xinvissued = (xinvissued*A), + X0 = (x0*B + x0tilde*A), + P = (b*B), + TId = (b*Xid), + TId = (tid*A), + TBucket = (b*Xbucket), + TBucket = (tbucket*A), + TInvIssued = (b*Xinvissued), + TInvIssued = (tinvissued*A), + EncQ0 = (s*B + tid*EncId0 + tbucket*EncBucket0 + tinvissued*EncInvIssued0), + EncQ1 = (s*D + tid*EncId1 + tbucket*EncBucket1 + + tinvissued*EncInvIssued1 + x0*P + xlevel*Plevel + xsince*Psince + + xinvremain*Pinvremain), + Xid_nm = (xid_nm*A), + Xfrom_nm = (xfrom_nm*A), + Xto_nm = (xto_nm*A), + X0_nm = (x0_nm*B + x0tilde_nm*A), + P_nm = (b_nm*B), + TId_nm = (b_nm*Xid_nm), + TId_nm = (tid_nm*A), + TBucket_nm = (b_nm*Xfrom_nm + b_nm*Xto_nm), + TBucket_nm = (tbucket_nm*A), + EncQ0_nm = (s_nm*B + tid_nm*EncId0 + tbucket_nm*EncBucket0), + EncQ1_nm = (s_nm*D + tid_nm*EncId1 + tbucket_nm*EncBucket1 + x0_nm*P_nm) +} + pub fn request( lox_cred: &cred::Lox, reach_cred: &cred::BucketReachability, @@ -231,7 +274,7 @@ pub fn request( Some(v) => v, None => return Err(ProofError::VerificationFailure), }; - if trust_level < 1 { + if trust_level < 1 || (trust_level as usize) > MAX_LEVEL { return Err(ProofError::VerificationFailure); } // The trust level has to be no higher than the highest level @@ -260,6 +303,12 @@ pub fn request( if reach_date != today { return Err(ProofError::VerificationFailure); } + // The new trust level + let new_level = if (trust_level as usize) < MAX_LEVEL { + trust_level + 1 + } else { + trust_level + }; // Blind showing the Lox credential @@ -331,7 +380,7 @@ pub fn request( // Encrypt the other blinded fields (times B) to D as well let ebucket = Scalar::random(&mut rng); let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D); - let newinvites: Scalar = LEVEL_INVITATIONS[trust_level as usize].into(); + let newinvites: Scalar = LEVEL_INVITATIONS[new_level as usize].into(); let einvissued = Scalar::random(&mut rng); let EncInvIssued = ( &einvissued * Btable, @@ -561,9 +610,366 @@ pub fn request( EncInvIssued, id_client, bucket: lox_cred.bucket, - level: lox_cred.trust_level + Scalar::one(), + level: new_level.into(), invremain: newinvites, invissued: lox_cred.invites_issued, }, )) } + +impl BridgeAuth { + /// Receive a level up request + pub fn handle_level_up(&mut self, req: Request) -> Result { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + if req.P.is_identity() { + return Err(ProofError::VerificationFailure); + } + + let today: Scalar = self.today().into(); + + // Get the level and ensure it's at most MAX_LEVEL + let level: usize = match scalar_u32(&req.level) { + Some(l) if l as usize <= MAX_LEVEL => l as usize, + _ => return Err(ProofError::VerificationFailure), + }; + + // Recompute the "error factors" using knowledge of our own + // (the issuer's) private key instead of knowledge of the + // hidden attributes + let Vprime = + (self.lox_priv.x[0] + self.lox_priv.x[1] * req.id + self.lox_priv.x[3] * req.level) + * req.P + + self.lox_priv.x[2] * req.CBucket + + self.lox_priv.x[4] * req.CSince + + self.lox_priv.x[5] * req.CInvRemain + + self.lox_priv.x[6] * req.CInvIssued + - req.CQ; + + let Vprime_reach = (self.reachability_priv.x[0] + self.reachability_priv.x[1] * today) + * req.P_reach + + self.reachability_priv.x[2] * req.CBucket_reach + - req.CQ_reach; + + // Recompute CG0 using Horner's method + let unt: Scalar = LEVEL_INTERVAL[level].into(); + let CG0prime = (today - unt) * req.P + - req.CSince + - pt_dbl( + &(pt_dbl( + &(pt_dbl( + &(pt_dbl( + &(pt_dbl( + &(pt_dbl(&(pt_dbl(&(pt_dbl(&req.CG8) + req.CG7)) + req.CG6)) + + req.CG5), + ) + req.CG4), + ) + req.CG3), + ) + req.CG2), + ) + req.CG1), + ); + + // Verify the ZKP + let mut transcript = Transcript::new(b"level upgrade request"); + requestproof::verify_compact( + &req.piUser, + &mut transcript, + requestproof::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P: &req.P.compress(), + CBucket: &req.CBucket.compress(), + CSince: &req.CSince.compress(), + CInvRemain: &req.CInvRemain.compress(), + CInvIssued: &req.CInvIssued.compress(), + V: &Vprime.compress(), + Xbucket: &self.lox_pub.X[2].compress(), + Xsince: &self.lox_pub.X[4].compress(), + Xinvremain: &self.lox_pub.X[5].compress(), + Xinvissued: &self.lox_pub.X[6].compress(), + P_reach: &req.P_reach.compress(), + CBucket_reach: &req.CBucket_reach.compress(), + V_reach: &Vprime_reach.compress(), + Xbucket_reach: &self.reachability_pub.X[2].compress(), + D: &req.D.compress(), + EncIdClient0: &req.EncIdClient.0.compress(), + EncIdClient1: &req.EncIdClient.1.compress(), + EncBucket0: &req.EncBucket.0.compress(), + EncBucket1: &req.EncBucket.1.compress(), + EncInvIssued0: &req.EncInvIssued.0.compress(), + EncInvIssued1: &req.EncInvIssued.1.compress(), + CG0: &CG0prime.compress(), + CG1: &req.CG1.compress(), + CG2: &req.CG2.compress(), + CG3: &req.CG3.compress(), + CG4: &req.CG4.compress(), + CG5: &req.CG5.compress(), + CG6: &req.CG6.compress(), + CG7: &req.CG7.compress(), + CG8: &req.CG8.compress(), + CG0sq: &req.CG0sq.compress(), + CG1sq: &req.CG1sq.compress(), + CG2sq: &req.CG2sq.compress(), + CG3sq: &req.CG3sq.compress(), + CG4sq: &req.CG4sq.compress(), + CG5sq: &req.CG5sq.compress(), + CG6sq: &req.CG6sq.compress(), + CG7sq: &req.CG7sq.compress(), + CG8sq: &req.CG8sq.compress(), + }, + )?; + + // Ensure the id has not been seen before, and add it to the + // seen list. + if self.id_filter.filter(&req.id) == SeenType::Seen { + return Err(ProofError::VerificationFailure); + } + + // Blind issuing of the new Lox credential + + // Choose a random server id component to add to the client's + // (blinded) id component + let mut rng = rand::thread_rng(); + let id_server = Scalar::random(&mut rng); + let EncId = (req.EncIdClient.0, req.EncIdClient.1 + &id_server * Btable); + + // Create the trust_level attrubute (Scalar), which will be + // one more than the current level, unless the current level is + // MAX_LEVEL, in which case it stays the same + let new_level = if level < MAX_LEVEL { level + 1 } else { level }; + let trust_level: Scalar = (new_level as u64).into(); + + // Create the level_since attribute (Scalar), which is today's + // Julian date + let level_since: Scalar = self.today().into(); + + // Create the invitations_remaining attribute (Scalar), which is + // the number of invitations at the new level + let invitations_remaining: Scalar = LEVEL_INVITATIONS[new_level].into(); + + // Compute the MAC on the visible attributes + let b = Scalar::random(&mut rng); + let P = &b * Btable; + let QHc = (self.lox_priv.x[0] + + self.lox_priv.x[3] * trust_level + + self.lox_priv.x[4] * level_since + + self.lox_priv.x[5] * invitations_remaining) + * P; + + // El Gamal encrypt it to the public key req.D + let s = Scalar::random(&mut rng); + let EncQHc = (&s * Btable, QHc + s * req.D); + + // Homomorphically compute the part of the MAC corresponding to + // the blinded attributes + let tid = self.lox_priv.x[1] * b; + let TId = &tid * Atable; + let EncQId = (tid * EncId.0, tid * EncId.1); + let tbucket = self.lox_priv.x[2] * b; + let TBucket = &tbucket * Atable; + let EncQBucket = (tbucket * req.EncBucket.0, tbucket * req.EncBucket.1); + let tinvissued = self.lox_priv.x[6] * b; + let TInvIssued = &tinvissued * Atable; + let EncQInvIssued = ( + tinvissued * req.EncInvIssued.0, + tinvissued * req.EncInvIssued.1, + ); + + let EncQ = ( + EncQHc.0 + EncQId.0 + EncQBucket.0 + EncQInvIssued.0, + EncQHc.1 + EncQId.1 + EncQBucket.1 + EncQInvIssued.1, + ); + + // Now the no-op migration credential + // Compute the MAC on the visible attributes (none here) + let b_nm = Scalar::random(&mut rng); + let P_nm = &b_nm * Btable; + let QHc_nm = (self.migration_priv.x[0]) * P_nm; + + // El Gamal encrypt it to the public key req.D + let s_nm = Scalar::random(&mut rng); + let EncQHc_nm = (&s_nm * Btable, QHc_nm + s_nm * req.D); + + // Homomorphically compute the part of the MAC corresponding to + // the blinded attributes + let tid_nm = self.migration_priv.x[1] * b_nm; + let TId_nm = &tid_nm * Atable; + let EncQId_nm = (tid_nm * EncId.0, tid_nm * EncId.1); + let tbucket_nm = (self.migration_priv.x[2] + self.migration_priv.x[3]) * b_nm; + let TBucket_nm = &tbucket_nm * Atable; + let EncQBucket_nm = (tbucket_nm * req.EncBucket.0, tbucket_nm * req.EncBucket.1); + + let EncQ_nm = ( + EncQHc_nm.0 + EncQId_nm.0 + EncQBucket_nm.0, + EncQHc_nm.1 + EncQId_nm.1 + EncQBucket_nm.1, + ); + + let mut transcript = Transcript::new(b"level upgrade issuing"); + let piBlindIssue = blindissue::prove_compact( + &mut transcript, + blindissue::ProveAssignments { + A: &A, + B: &B, + P: &P, + EncQ0: &EncQ.0, + EncQ1: &EncQ.1, + X0: &self.lox_pub.X[0], + Xid: &self.lox_pub.X[1], + Xbucket: &self.lox_pub.X[2], + Xlevel: &self.lox_pub.X[3], + Xsince: &self.lox_pub.X[4], + Xinvremain: &self.lox_pub.X[5], + Xinvissued: &self.lox_pub.X[6], + Plevel: &(trust_level * P), + Psince: &(level_since * P), + Pinvremain: &(invitations_remaining * P), + TId: &TId, + TBucket: &TBucket, + TInvIssued: &TInvIssued, + P_nm: &P_nm, + EncQ0_nm: &EncQ_nm.0, + EncQ1_nm: &EncQ_nm.1, + X0_nm: &self.migration_pub.X[0], + Xid_nm: &self.migration_pub.X[1], + Xfrom_nm: &self.migration_pub.X[2], + Xto_nm: &self.migration_pub.X[3], + TId_nm: &TId_nm, + TBucket_nm: &TBucket_nm, + D: &req.D, + EncId0: &EncId.0, + EncId1: &EncId.1, + EncBucket0: &req.EncBucket.0, + EncBucket1: &req.EncBucket.1, + EncInvIssued0: &req.EncInvIssued.0, + EncInvIssued1: &req.EncInvIssued.1, + x0: &self.lox_priv.x[0], + x0tilde: &self.lox_priv.x0tilde, + xid: &self.lox_priv.x[1], + xbucket: &self.lox_priv.x[2], + xlevel: &self.lox_priv.x[3], + xsince: &self.lox_priv.x[4], + xinvremain: &self.lox_priv.x[5], + xinvissued: &self.lox_priv.x[6], + s: &s, + b: &b, + tid: &tid, + tbucket: &tbucket, + tinvissued: &tinvissued, + x0_nm: &self.migration_priv.x[0], + x0tilde_nm: &self.migration_priv.x0tilde, + xid_nm: &self.migration_priv.x[1], + xfrom_nm: &self.migration_priv.x[2], + xto_nm: &self.migration_priv.x[3], + s_nm: &s_nm, + b_nm: &b_nm, + tid_nm: &tid_nm, + tbucket_nm: &tbucket_nm, + }, + ) + .0; + + Ok(Response { + P, + EncQ, + id_server, + level_since, + TId, + TBucket, + TInvIssued, + P_nm, + EncQ_nm, + TId_nm, + TBucket_nm, + piBlindIssue, + }) + } +} + +/// Handle the response to the request, producing the new Lox credential +/// if successful. +pub fn handle_response( + state: State, + resp: Response, + lox_pub: &IssuerPubKey, + migration_pub: &IssuerPubKey, +) -> Result { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + if resp.P.is_identity() || resp.P_nm.is_identity() { + return Err(ProofError::VerificationFailure); + } + + // Add the server's contribution to the id to our own, both in plain + // and encrypted form + let id = state.id_client + resp.id_server; + let EncId = ( + state.EncIdClient.0, + state.EncIdClient.1 + &resp.id_server * Btable, + ); + + // Verify the proof + let mut transcript = Transcript::new(b"level upgrade issuing"); + blindissue::verify_compact( + &resp.piBlindIssue, + &mut transcript, + blindissue::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P: &resp.P.compress(), + EncQ0: &resp.EncQ.0.compress(), + EncQ1: &resp.EncQ.1.compress(), + X0: &lox_pub.X[0].compress(), + Xid: &lox_pub.X[1].compress(), + Xbucket: &lox_pub.X[2].compress(), + Xlevel: &lox_pub.X[3].compress(), + Xsince: &lox_pub.X[4].compress(), + Xinvremain: &lox_pub.X[5].compress(), + Xinvissued: &lox_pub.X[6].compress(), + Plevel: &(state.level * resp.P).compress(), + Psince: &(resp.level_since * resp.P).compress(), + Pinvremain: &(state.invremain * resp.P).compress(), + TId: &resp.TId.compress(), + TBucket: &resp.TBucket.compress(), + TInvIssued: &resp.TInvIssued.compress(), + P_nm: &resp.P_nm.compress(), + EncQ0_nm: &resp.EncQ_nm.0.compress(), + EncQ1_nm: &resp.EncQ_nm.1.compress(), + X0_nm: &migration_pub.X[0].compress(), + Xid_nm: &migration_pub.X[1].compress(), + Xfrom_nm: &migration_pub.X[2].compress(), + Xto_nm: &migration_pub.X[3].compress(), + TId_nm: &resp.TId_nm.compress(), + TBucket_nm: &resp.TBucket_nm.compress(), + D: &state.D.compress(), + EncId0: &EncId.0.compress(), + EncId1: &EncId.1.compress(), + EncBucket0: &state.EncBucket.0.compress(), + EncBucket1: &state.EncBucket.1.compress(), + EncInvIssued0: &state.EncInvIssued.0.compress(), + EncInvIssued1: &state.EncInvIssued.1.compress(), + }, + )?; + + // Decrypt EncQ + let Q = resp.EncQ.1 - (state.d * resp.EncQ.0); + + // Decrypt EncQ_nm + let Q_nm = resp.EncQ_nm.1 - (state.d * resp.EncQ_nm.0); + + Ok(cred::Lox { + P: resp.P, + Q, + id, + bucket: state.bucket, + trust_level: state.level, + level_since: resp.level_since, + invites_remaining: state.invremain, + invites_issued: state.invissued, + P_noopmigration: resp.P_nm, + Q_noopmigration: Q_nm, + }) +} diff --git a/crates/lox-library/src/proto/migration.rs b/crates/lox-library/src/proto/migration.rs index 72964ee..6d5a2bc 100644 --- a/crates/lox-library/src/proto/migration.rs +++ b/crates/lox-library/src/proto/migration.rs @@ -428,7 +428,7 @@ impl BridgeAuth { let EncQHc = (&s * Btable, QHc + s * req.D); // Homomorphically compute the part of the MAC corresponding to - // the blinded id attribute + // the blinded attributes let tid = self.lox_priv.x[1] * b; let TId = &tid * Atable; let EncQId = (tid * EncId.0, tid * EncId.1); diff --git a/crates/lox-library/src/proto/trust_promotion.rs b/crates/lox-library/src/proto/trust_promotion.rs index 6c4ddac..578e584 100644 --- a/crates/lox-library/src/proto/trust_promotion.rs +++ b/crates/lox-library/src/proto/trust_promotion.rs @@ -485,7 +485,7 @@ impl BridgeAuth { )?; // Ensure the id has not been seen before, either in the general - // if filter, or the filter specifically for trust promotion. + // id filter, or the filter specifically for trust promotion. // Add the id to the latter, but not the former. if self.id_filter.check(&req.id) == SeenType::Seen || self.trust_promotion_filter.filter(&req.id) == SeenType::Seen diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index bb40cda..b544560 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -147,25 +147,57 @@ fn test_level0_migration() { assert!(ba.verify_reachability(&bucket.1.unwrap())); } -#[test] -fn test_level_up() { - let (bdb, mut ba) = setup(); - let loxcred = level0_migration(&bdb, &mut ba); - - // Time passes - ba.advance_days(20); - - let (id, key) = bridge_table::from_scalar(loxcred.bucket).unwrap(); +fn level_up(ba: &mut BridgeAuth, cred: &cred::Lox) -> cred::Lox { + // Read the bucket in the credential to get today's Bucket + // Reachability credential + let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); let encbuckets = ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); let reachcred = bucket.1.unwrap(); + + // Use the Bucket Reachability credential to advance to the next + // level let (req, state) = level_up::request( - &loxcred, + &cred, &reachcred, &ba.lox_pub, &ba.reachability_pub, ba.today(), ) .unwrap(); + let resp = ba.handle_level_up(req).unwrap(); + let cred = level_up::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); + cred +} + +#[test] +fn test_level_up() { + let (bdb, mut ba) = setup(); + let cred1 = level0_migration(&bdb, &mut ba); + assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); + + // Time passes + ba.advance_days(20); + + let cred2 = level_up(&mut ba, &cred1); + assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); + println!("cred2 = {:?}", cred2); + assert!(ba.verify_lox(&cred2)); + + // Time passes + ba.advance_days(30); + + let cred3 = level_up(&mut ba, &cred2); + assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); + println!("cred3 = {:?}", cred3); + assert!(ba.verify_lox(&cred3)); + + // Time passes + ba.advance_days(60); + + let cred4 = level_up(&mut ba, &cred3); + assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); + println!("cred4 = {:?}", cred4); + assert!(ba.verify_lox(&cred4)); } From ecef59392b76314a9925f17016b5ac6e6cd0c67a Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Mon, 3 May 2021 11:44:42 -0400 Subject: [PATCH 032/115] Fix the rust in a couple of places --- crates/lox-library/src/bridge_table.rs | 4 ++-- crates/lox-library/src/migration_table.rs | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index 43823be..c341d72 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -121,8 +121,8 @@ impl BridgeLine { + reachability_priv.x[2] * bucket_attr)) * Btable; res[pos..pos + 4].copy_from_slice(&today.to_le_bytes()); - res[pos + 4..pos + 36].copy_from_slice(&P.compress().as_bytes()[..]); - res[pos + 36..].copy_from_slice(&Q.compress().as_bytes()[..]); + res[pos + 4..pos + 36].copy_from_slice(P.compress().as_bytes()); + res[pos + 36..].copy_from_slice(Q.compress().as_bytes()); } res } diff --git a/crates/lox-library/src/migration_table.rs b/crates/lox-library/src/migration_table.rs index 7973d7a..7bf5357 100644 --- a/crates/lox-library/src/migration_table.rs +++ b/crates/lox-library/src/migration_table.rs @@ -82,9 +82,9 @@ pub fn encrypt_cred( // Serialize (to_bucket, P, Q) let mut credbytes: [u8; MIGRATION_BYTES] = [0; MIGRATION_BYTES]; - credbytes[0..32].copy_from_slice(&to_bucket.as_bytes()[..]); - credbytes[32..64].copy_from_slice(&P.compress().as_bytes()[..]); - credbytes[64..].copy_from_slice(&Q.compress().as_bytes()[..]); + credbytes[0..32].copy_from_slice(to_bucket.as_bytes()); + credbytes[32..64].copy_from_slice(P.compress().as_bytes()); + credbytes[64..].copy_from_slice(Q.compress().as_bytes()); // Pick a random nonce let mut noncebytes: [u8; 12] = [0; 12]; @@ -93,9 +93,9 @@ pub fn encrypt_cred( // Compute the hash of (id, from_bucket, Qk) let mut hasher = Sha256::new(); - hasher.update(&id.as_bytes()[..]); - hasher.update(&from_bucket.as_bytes()[..]); - hasher.update(&Qk.compress().as_bytes()[..]); + hasher.update(id.as_bytes()); + hasher.update(from_bucket.as_bytes()); + hasher.update(Qk.compress().as_bytes()); let fullhash = hasher.finalize(); // Create the encryption key from the 2nd half of the hash @@ -182,9 +182,9 @@ pub fn decrypt_cred( ) -> Option { // Compute the hash of (id, from_bucket, Qk) let mut hasher = Sha256::new(); - hasher.update(&lox_id.as_bytes()[..]); - hasher.update(&from_bucket.as_bytes()[..]); - hasher.update(&Qk.compress().as_bytes()[..]); + hasher.update(lox_id.as_bytes()); + hasher.update(from_bucket.as_bytes()); + hasher.update(Qk.compress().as_bytes()); let fullhash = hasher.finalize(); // Use the first half of the above hash as the label From 15e9a1a72a1d2a2ad076c9480103f3000d74cec6 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Mon, 3 May 2021 14:13:13 -0400 Subject: [PATCH 033/115] Remove noop migration credentials --- crates/lox-library/src/cred.rs | 9 +-- crates/lox-library/src/lib.rs | 10 +-- crates/lox-library/src/proto/level_up.rs | 87 +-------------------- crates/lox-library/src/proto/migration.rs | 87 +-------------------- crates/lox-library/src/proto/open_invite.rs | 83 +------------------- crates/lox-library/src/tests.rs | 9 +-- 6 files changed, 16 insertions(+), 269 deletions(-) diff --git a/crates/lox-library/src/cred.rs b/crates/lox-library/src/cred.rs index 2d32b4d..5839f13 100644 --- a/crates/lox-library/src/cred.rs +++ b/crates/lox-library/src/cred.rs @@ -25,12 +25,7 @@ pub struct Migration { /// 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 /// Julian date of when this user was changed to the current trust -/// level. (P_noopmigration, Q_noopmigration) are the MAC on the -/// implicit no-op migration credential formed by the attributes (id, -/// bucket, bucket), which authorizes the user to switch from its -/// current bucket to the same bucket (i.e., a no-op). This can be -/// useful for hiding from the BA whether or not the user is performing -/// a bucket migration. +/// level. #[derive(Debug)] pub struct Lox { pub P: RistrettoPoint, @@ -41,8 +36,6 @@ pub struct Lox { pub level_since: Scalar, pub invites_remaining: Scalar, pub invites_issued: Scalar, - pub P_noopmigration: RistrettoPoint, - pub Q_noopmigration: RistrettoPoint, } /// The migration key credential. diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 37338a8..8b3e7d5 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -283,7 +283,7 @@ impl BridgeAuth { #[cfg(test)] /// Verify the two MACs on a Lox credential pub fn verify_lox(&self, cred: &cred::Lox) -> bool { - if cred.P.is_identity() || cred.P_noopmigration.is_identity() { + if cred.P.is_identity() { return false; } @@ -296,13 +296,7 @@ impl BridgeAuth { + cred.invites_issued * self.lox_priv.x[6]) * cred.P; - let Q_noopmigration = (self.migration_priv.x[0] - + cred.id * self.migration_priv.x[1] - + cred.bucket * self.migration_priv.x[2] - + cred.bucket * self.migration_priv.x[3]) - * cred.P_noopmigration; - - return Q == cred.Q && Q_noopmigration == cred.Q_noopmigration; + return Q == cred.Q; } #[cfg(test)] diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs index faf4cdc..f260c0a 100644 --- a/crates/lox-library/src/proto/level_up.rs +++ b/crates/lox-library/src/proto/level_up.rs @@ -143,12 +143,6 @@ pub struct Response { TBucket: RistrettoPoint, TInvIssued: RistrettoPoint, - // The fields for the implicit noop migration ("nm") credential - P_nm: RistrettoPoint, - EncQ_nm: (RistrettoPoint, RistrettoPoint), - TId_nm: RistrettoPoint, - TBucket_nm: RistrettoPoint, - // The ZKP piBlindIssue: CompactProof, } @@ -211,12 +205,9 @@ define_proof! { blindissue, "Level Upgrade Issuing", (x0, x0tilde, xid, xbucket, xlevel, xsince, xinvremain, xinvissued, - s, b, tid, tbucket, tinvissued, - x0_nm, x0tilde_nm, xid_nm, xfrom_nm, xto_nm, s_nm, b_nm, tid_nm, tbucket_nm), + s, b, tid, tbucket, tinvissued), (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xlevel, Xsince, Xinvremain, Xinvissued, Plevel, Psince, Pinvremain, TId, TBucket, TInvIssued, - P_nm, EncQ0_nm, EncQ1_nm, X0_nm, Xid_nm, Xfrom_nm, Xto_nm, - TId_nm, TBucket_nm, D, EncId0, EncId1, EncBucket0, EncBucket1, EncInvIssued0, EncInvIssued1), (A, B): Xid = (xid*A), @@ -237,18 +228,7 @@ define_proof! { EncQ0 = (s*B + tid*EncId0 + tbucket*EncBucket0 + tinvissued*EncInvIssued0), EncQ1 = (s*D + tid*EncId1 + tbucket*EncBucket1 + tinvissued*EncInvIssued1 + x0*P + xlevel*Plevel + xsince*Psince - + xinvremain*Pinvremain), - Xid_nm = (xid_nm*A), - Xfrom_nm = (xfrom_nm*A), - Xto_nm = (xto_nm*A), - X0_nm = (x0_nm*B + x0tilde_nm*A), - P_nm = (b_nm*B), - TId_nm = (b_nm*Xid_nm), - TId_nm = (tid_nm*A), - TBucket_nm = (b_nm*Xfrom_nm + b_nm*Xto_nm), - TBucket_nm = (tbucket_nm*A), - EncQ0_nm = (s_nm*B + tid_nm*EncId0 + tbucket_nm*EncBucket0), - EncQ1_nm = (s_nm*D + tid_nm*EncId1 + tbucket_nm*EncBucket1 + x0_nm*P_nm) + + xinvremain*Pinvremain) } pub fn request( @@ -782,30 +762,6 @@ impl BridgeAuth { EncQHc.1 + EncQId.1 + EncQBucket.1 + EncQInvIssued.1, ); - // Now the no-op migration credential - // Compute the MAC on the visible attributes (none here) - let b_nm = Scalar::random(&mut rng); - let P_nm = &b_nm * Btable; - let QHc_nm = (self.migration_priv.x[0]) * P_nm; - - // El Gamal encrypt it to the public key req.D - let s_nm = Scalar::random(&mut rng); - let EncQHc_nm = (&s_nm * Btable, QHc_nm + s_nm * req.D); - - // Homomorphically compute the part of the MAC corresponding to - // the blinded attributes - let tid_nm = self.migration_priv.x[1] * b_nm; - let TId_nm = &tid_nm * Atable; - let EncQId_nm = (tid_nm * EncId.0, tid_nm * EncId.1); - let tbucket_nm = (self.migration_priv.x[2] + self.migration_priv.x[3]) * b_nm; - let TBucket_nm = &tbucket_nm * Atable; - let EncQBucket_nm = (tbucket_nm * req.EncBucket.0, tbucket_nm * req.EncBucket.1); - - let EncQ_nm = ( - EncQHc_nm.0 + EncQId_nm.0 + EncQBucket_nm.0, - EncQHc_nm.1 + EncQId_nm.1 + EncQBucket_nm.1, - ); - let mut transcript = Transcript::new(b"level upgrade issuing"); let piBlindIssue = blindissue::prove_compact( &mut transcript, @@ -828,15 +784,6 @@ impl BridgeAuth { TId: &TId, TBucket: &TBucket, TInvIssued: &TInvIssued, - P_nm: &P_nm, - EncQ0_nm: &EncQ_nm.0, - EncQ1_nm: &EncQ_nm.1, - X0_nm: &self.migration_pub.X[0], - Xid_nm: &self.migration_pub.X[1], - Xfrom_nm: &self.migration_pub.X[2], - Xto_nm: &self.migration_pub.X[3], - TId_nm: &TId_nm, - TBucket_nm: &TBucket_nm, D: &req.D, EncId0: &EncId.0, EncId1: &EncId.1, @@ -857,15 +804,6 @@ impl BridgeAuth { tid: &tid, tbucket: &tbucket, tinvissued: &tinvissued, - x0_nm: &self.migration_priv.x[0], - x0tilde_nm: &self.migration_priv.x0tilde, - xid_nm: &self.migration_priv.x[1], - xfrom_nm: &self.migration_priv.x[2], - xto_nm: &self.migration_priv.x[3], - s_nm: &s_nm, - b_nm: &b_nm, - tid_nm: &tid_nm, - tbucket_nm: &tbucket_nm, }, ) .0; @@ -878,10 +816,6 @@ impl BridgeAuth { TId, TBucket, TInvIssued, - P_nm, - EncQ_nm, - TId_nm, - TBucket_nm, piBlindIssue, }) } @@ -893,13 +827,12 @@ pub fn handle_response( state: State, resp: Response, lox_pub: &IssuerPubKey, - migration_pub: &IssuerPubKey, ) -> Result { let A: &RistrettoPoint = &CMZ_A; let B: &RistrettoPoint = &CMZ_B; let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; - if resp.P.is_identity() || resp.P_nm.is_identity() { + if resp.P.is_identity() { return Err(ProofError::VerificationFailure); } @@ -935,15 +868,6 @@ pub fn handle_response( TId: &resp.TId.compress(), TBucket: &resp.TBucket.compress(), TInvIssued: &resp.TInvIssued.compress(), - P_nm: &resp.P_nm.compress(), - EncQ0_nm: &resp.EncQ_nm.0.compress(), - EncQ1_nm: &resp.EncQ_nm.1.compress(), - X0_nm: &migration_pub.X[0].compress(), - Xid_nm: &migration_pub.X[1].compress(), - Xfrom_nm: &migration_pub.X[2].compress(), - Xto_nm: &migration_pub.X[3].compress(), - TId_nm: &resp.TId_nm.compress(), - TBucket_nm: &resp.TBucket_nm.compress(), D: &state.D.compress(), EncId0: &EncId.0.compress(), EncId1: &EncId.1.compress(), @@ -957,9 +881,6 @@ pub fn handle_response( // Decrypt EncQ let Q = resp.EncQ.1 - (state.d * resp.EncQ.0); - // Decrypt EncQ_nm - let Q_nm = resp.EncQ_nm.1 - (state.d * resp.EncQ_nm.0); - Ok(cred::Lox { P: resp.P, Q, @@ -969,7 +890,5 @@ pub fn handle_response( level_since: resp.level_since, invites_remaining: state.invremain, invites_issued: state.invissued, - P_noopmigration: resp.P_nm, - Q_noopmigration: Q_nm, }) } diff --git a/crates/lox-library/src/proto/migration.rs b/crates/lox-library/src/proto/migration.rs index 6d5a2bc..b20badb 100644 --- a/crates/lox-library/src/proto/migration.rs +++ b/crates/lox-library/src/proto/migration.rs @@ -92,12 +92,6 @@ pub struct Response { TId: RistrettoPoint, TBucket: RistrettoPoint, - // The fields for the implicit noop migration ("nm") credential - P_nm: RistrettoPoint, - EncQ_nm: (RistrettoPoint, RistrettoPoint), - TId_nm: RistrettoPoint, - TBucket_nm: RistrettoPoint, - // The ZKP piBlindIssue: CompactProof, } @@ -133,11 +127,8 @@ define_proof! { define_proof! { blindissue, "Migration Blind Issuing", - (x0, x0tilde, xid, xbucket, xlevel, xsince, s, b, tid, tbucket, - x0_nm, x0tilde_nm, xid_nm, xfrom_nm, xto_nm, s_nm, b_nm, tid_nm, tbucket_nm), + (x0, x0tilde, xid, xbucket, xlevel, xsince, s, b, tid, tbucket), (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xlevel, Xsince, Plevel, Psince, TId, TBucket, - P_nm, EncQ0_nm, EncQ1_nm, X0_nm, Xid_nm, Xfrom_nm, Xto_nm, - TId_nm, TBucket_nm, D, EncId0, EncId1, EncBucket0, EncBucket1), (A, B): Xid = (xid*A), @@ -151,18 +142,7 @@ define_proof! { TBucket = (b*Xbucket), TBucket = (tbucket*A), EncQ0 = (s*B + tid*EncId0 + tbucket*EncBucket0), - EncQ1 = (s*D + tid*EncId1 + tbucket*EncBucket1 + x0*P + xlevel*Plevel + xsince*Psince), - Xid_nm = (xid_nm*A), - Xfrom_nm = (xfrom_nm*A), - Xto_nm = (xto_nm*A), - X0_nm = (x0_nm*B + x0tilde_nm*A), - P_nm = (b_nm*B), - TId_nm = (b_nm*Xid_nm), - TId_nm = (tid_nm*A), - TBucket_nm = (b_nm*Xfrom_nm + b_nm*Xto_nm), - TBucket_nm = (tbucket_nm*A), - EncQ0_nm = (s_nm*B + tid_nm*EncId0 + tbucket_nm*EncBucket0), - EncQ1_nm = (s_nm*D + tid_nm*EncId1 + tbucket_nm*EncBucket1 + x0_nm*P_nm) + EncQ1 = (s*D + tid*EncId1 + tbucket*EncBucket1 + x0*P + xlevel*Plevel + xsince*Psince) } pub fn request( @@ -441,30 +421,6 @@ impl BridgeAuth { EncQHc.1 + EncQId.1 + EncQBucket.1, ); - // Now the no-op migration credential - // Compute the MAC on the visible attributes (none here) - let b_nm = Scalar::random(&mut rng); - let P_nm = &b_nm * Btable; - let QHc_nm = (self.migration_priv.x[0]) * P_nm; - - // El Gamal encrypt it to the public key req.D - let s_nm = Scalar::random(&mut rng); - let EncQHc_nm = (&s_nm * Btable, QHc_nm + s_nm * req.D); - - // Homomorphically compute the part of the MAC corresponding to - // the blinded attributes - let tid_nm = self.migration_priv.x[1] * b_nm; - let TId_nm = &tid_nm * Atable; - let EncQId_nm = (tid_nm * EncId.0, tid_nm * EncId.1); - let tbucket_nm = (self.migration_priv.x[2] + self.migration_priv.x[3]) * b_nm; - let TBucket_nm = &tbucket_nm * Atable; - let EncQBucket_nm = (tbucket_nm * req.EncBucket.0, tbucket_nm * req.EncBucket.1); - - let EncQ_nm = ( - EncQHc_nm.0 + EncQId_nm.0 + EncQBucket_nm.0, - EncQHc_nm.1 + EncQId_nm.1 + EncQBucket_nm.1, - ); - let mut transcript = Transcript::new(b"migration issuing"); let piBlindIssue = blindissue::prove_compact( &mut transcript, @@ -483,15 +439,6 @@ impl BridgeAuth { Psince: &(level_since * P), TId: &TId, TBucket: &TBucket, - P_nm: &P_nm, - EncQ0_nm: &EncQ_nm.0, - EncQ1_nm: &EncQ_nm.1, - X0_nm: &self.migration_pub.X[0], - Xid_nm: &self.migration_pub.X[1], - Xfrom_nm: &self.migration_pub.X[2], - Xto_nm: &self.migration_pub.X[3], - TId_nm: &TId_nm, - TBucket_nm: &TBucket_nm, D: &req.D, EncId0: &EncId.0, EncId1: &EncId.1, @@ -507,15 +454,6 @@ impl BridgeAuth { b: &b, tid: &tid, tbucket: &tbucket, - x0_nm: &self.migration_priv.x[0], - x0tilde_nm: &self.migration_priv.x0tilde, - xid_nm: &self.migration_priv.x[1], - xfrom_nm: &self.migration_priv.x[2], - xto_nm: &self.migration_priv.x[3], - s_nm: &s_nm, - b_nm: &b_nm, - tid_nm: &tid_nm, - tbucket_nm: &tbucket_nm, }, ) .0; @@ -527,10 +465,6 @@ impl BridgeAuth { id_server, TId, TBucket, - P_nm, - EncQ_nm, - TId_nm, - TBucket_nm, piBlindIssue, }) } @@ -542,13 +476,12 @@ pub fn handle_response( state: State, resp: Response, lox_pub: &IssuerPubKey, - migration_pub: &IssuerPubKey, ) -> Result { let A: &RistrettoPoint = &CMZ_A; let B: &RistrettoPoint = &CMZ_B; let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; - if resp.P.is_identity() || resp.P_nm.is_identity() { + if resp.P.is_identity() { return Err(ProofError::VerificationFailure); } @@ -581,15 +514,6 @@ pub fn handle_response( Psince: &(resp.level_since * resp.P).compress(), TId: &resp.TId.compress(), TBucket: &resp.TBucket.compress(), - P_nm: &resp.P_nm.compress(), - EncQ0_nm: &resp.EncQ_nm.0.compress(), - EncQ1_nm: &resp.EncQ_nm.1.compress(), - X0_nm: &migration_pub.X[0].compress(), - Xid_nm: &migration_pub.X[1].compress(), - Xfrom_nm: &migration_pub.X[2].compress(), - Xto_nm: &migration_pub.X[3].compress(), - TId_nm: &resp.TId_nm.compress(), - TBucket_nm: &resp.TBucket_nm.compress(), D: &state.D.compress(), EncId0: &EncId.0.compress(), EncId1: &EncId.1.compress(), @@ -601,9 +525,6 @@ pub fn handle_response( // Decrypt EncQ let Q = resp.EncQ.1 - (state.d * resp.EncQ.0); - // Decrypt EncQ_nm - let Q_nm = resp.EncQ_nm.1 - (state.d * resp.EncQ_nm.0); - Ok(cred::Lox { P: resp.P, Q, @@ -613,7 +534,5 @@ pub fn handle_response( level_since: resp.level_since, invites_remaining: Scalar::zero(), invites_issued: Scalar::zero(), - P_noopmigration: resp.P_nm, - Q_noopmigration: Q_nm, }) } diff --git a/crates/lox-library/src/proto/open_invite.rs b/crates/lox-library/src/proto/open_invite.rs index b88f66e..7754541 100644 --- a/crates/lox-library/src/proto/open_invite.rs +++ b/crates/lox-library/src/proto/open_invite.rs @@ -54,9 +54,6 @@ pub struct Response { TId: RistrettoPoint, bucket: Scalar, level_since: Scalar, - P_noopmigration: RistrettoPoint, - EncQ_noopmigration: (RistrettoPoint, RistrettoPoint), - TId_noopmigration: RistrettoPoint, piBlindIssue: CompactProof, } @@ -76,11 +73,8 @@ define_proof! { define_proof! { blindissue, "Open Invitation Blind Issuing", - (x0, x0tilde, xid, xbucket, xsince, s, b, tid, - x0_nm, x0tilde_nm, xid_nm, xfrom_nm, xto_nm, s_nm, b_nm, tid_nm), + (x0, x0tilde, xid, xbucket, xsince, s, b, tid), (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xsince, Pbucket, Psince, TId, - P_nm, EncQ0_nm, EncQ1_nm, X0_nm, Xid_nm, Xfrom_nm, Xto_nm, - Pbucket_nm, TId_nm, D, EncId0, EncId1), (A, B) : Xid = (xid*A), @@ -91,16 +85,7 @@ define_proof! { TId = (b*Xid), TId = (tid*A), EncQ0 = (s*B + tid*EncId0), - EncQ1 = (s*D + tid*EncId1 + x0*P + xbucket*Pbucket + xsince*Psince), - Xid_nm = (xid_nm*A), - Xfrom_nm = (xfrom_nm*A), - Xto_nm = (xto_nm*A), - X0_nm = (x0_nm*B + x0tilde_nm*A), - P_nm = (b_nm*B), - TId_nm = (b_nm*Xid_nm), - TId_nm = (tid_nm*A), - EncQ0_nm = (s_nm*B + tid_nm*EncId0), - EncQ1_nm = (s_nm*D + tid_nm*EncId1 + x0_nm*P_nm + xfrom_nm*Pbucket_nm + xto_nm*Pbucket_nm) + EncQ1 = (s*D + tid*EncId1 + x0*P + xbucket*Pbucket + xsince*Psince) } /// Submit an open invitation issued by the BridgeDb to receive your @@ -229,33 +214,6 @@ impl BridgeAuth { let EncQ = (EncQHc.0 + EncQId.0, EncQHc.1 + EncQId.1); - // Now the no-op migration credential - // Compute the MAC on the visible attributes - let b_noopmigration = Scalar::random(&mut rng); - let P_noopmigration = &b_noopmigration * Btable; - let QHc_noopmigration = (self.migration_priv.x[0] - + self.migration_priv.x[2] * bucket - + self.migration_priv.x[3] * bucket) - * P_noopmigration; - - // El Gamal encrypt it to the public key req.D - let s_noopmigration = Scalar::random(&mut rng); - let EncQHc_noopmigration = ( - &s_noopmigration * Btable, - QHc_noopmigration + s_noopmigration * req.D, - ); - - // Homomorphically compute the part of the MAC corresponding to - // the blinded id attribute - let tid_noopmigration = self.migration_priv.x[1] * b_noopmigration; - let TId_noopmigration = &tid_noopmigration * Atable; - let EncQId_noopmigration = (tid_noopmigration * EncId.0, tid_noopmigration * EncId.1); - - let EncQ_noopmigration = ( - EncQHc_noopmigration.0 + EncQId_noopmigration.0, - EncQHc_noopmigration.1 + EncQId_noopmigration.1, - ); - let mut transcript = Transcript::new(b"open invite issuing"); let piBlindIssue = blindissue::prove_compact( &mut transcript, @@ -272,15 +230,6 @@ impl BridgeAuth { Pbucket: &(bucket * P), Psince: &(level_since * P), TId: &TId, - P_nm: &P_noopmigration, - EncQ0_nm: &EncQ_noopmigration.0, - EncQ1_nm: &EncQ_noopmigration.1, - X0_nm: &self.migration_pub.X[0], - Xid_nm: &self.migration_pub.X[1], - Xfrom_nm: &self.migration_pub.X[2], - Xto_nm: &self.migration_pub.X[3], - Pbucket_nm: &(bucket * P_noopmigration), - TId_nm: &TId_noopmigration, D: &req.D, EncId0: &EncId.0, EncId1: &EncId.1, @@ -292,14 +241,6 @@ impl BridgeAuth { s: &s, b: &b, tid: &tid, - x0_nm: &self.migration_priv.x[0], - x0tilde_nm: &self.migration_priv.x0tilde, - xid_nm: &self.migration_priv.x[1], - xfrom_nm: &self.migration_priv.x[2], - xto_nm: &self.migration_priv.x[3], - s_nm: &s_noopmigration, - b_nm: &b_noopmigration, - tid_nm: &tid_noopmigration, }, ) .0; @@ -311,9 +252,6 @@ impl BridgeAuth { TId, bucket, level_since, - P_noopmigration, - EncQ_noopmigration, - TId_noopmigration, piBlindIssue, }) } @@ -325,13 +263,12 @@ pub fn handle_response( state: State, resp: Response, lox_pub: &IssuerPubKey, - migration_pub: &IssuerPubKey, ) -> Result { let A: &RistrettoPoint = &CMZ_A; let B: &RistrettoPoint = &CMZ_B; let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; - if resp.P.is_identity() || resp.P_noopmigration.is_identity() { + if resp.P.is_identity() { return Err(ProofError::VerificationFailure); } @@ -361,15 +298,6 @@ pub fn handle_response( Pbucket: &(resp.bucket * resp.P).compress(), Psince: &(resp.level_since * resp.P).compress(), TId: &resp.TId.compress(), - P_nm: &resp.P_noopmigration.compress(), - EncQ0_nm: &resp.EncQ_noopmigration.0.compress(), - EncQ1_nm: &resp.EncQ_noopmigration.1.compress(), - X0_nm: &migration_pub.X[0].compress(), - Xid_nm: &migration_pub.X[1].compress(), - Xfrom_nm: &migration_pub.X[2].compress(), - Xto_nm: &migration_pub.X[3].compress(), - Pbucket_nm: &(resp.bucket * resp.P_noopmigration).compress(), - TId_nm: &resp.TId_noopmigration.compress(), D: &state.D.compress(), EncId0: &EncId.0.compress(), EncId1: &EncId.1.compress(), @@ -379,9 +307,6 @@ pub fn handle_response( // Decrypt EncQ let Q = resp.EncQ.1 - (state.d * resp.EncQ.0); - // Decrypt EncQ_noopmigration - let Q_noopmigration = resp.EncQ_noopmigration.1 - (state.d * resp.EncQ_noopmigration.0); - Ok(cred::Lox { P: resp.P, Q, @@ -391,7 +316,5 @@ pub fn handle_response( level_since: resp.level_since, invites_remaining: Scalar::zero(), invites_issued: Scalar::zero(), - P_noopmigration: resp.P_noopmigration, - Q_noopmigration, }) } diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index b544560..d8ef0fc 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -36,7 +36,7 @@ fn test_open_invite() { // Use it to get a Lox credential let (req, state) = open_invite::request(&inv); let resp = ba.handle_open_invite(req).unwrap(); - let cred = open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); + let cred = open_invite::handle_response(state, resp, &ba.lox_pub).unwrap(); // Check that we can use the credential to read a bucket let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); @@ -89,7 +89,7 @@ fn trust_promotion(bdb: &BridgeDb, ba: &mut BridgeAuth) -> (cred::Lox, cred::Mig // Use it to get a Lox credential let (req, state) = open_invite::request(&inv); let resp = ba.handle_open_invite(req).unwrap(); - let cred = open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); + let cred = open_invite::handle_response(state, resp, &ba.lox_pub).unwrap(); assert!(ba.verify_lox(&cred)); // Time passes @@ -125,8 +125,7 @@ fn level0_migration(bdb: &BridgeDb, ba: &mut BridgeAuth) -> cred::Lox { let (migreq, migstate) = migration::request(&loxcred, &migcred, &ba.lox_pub, &ba.migration_pub).unwrap(); let migresp = ba.handle_migration(migreq).unwrap(); - let newloxcred = - migration::handle_response(migstate, migresp, &ba.lox_pub, &ba.migration_pub).unwrap(); + let newloxcred = migration::handle_response(migstate, migresp, &ba.lox_pub).unwrap(); newloxcred } @@ -167,7 +166,7 @@ fn level_up(ba: &mut BridgeAuth, cred: &cred::Lox) -> cred::Lox { ) .unwrap(); let resp = ba.handle_level_up(req).unwrap(); - let cred = level_up::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap(); + let cred = level_up::handle_response(state, resp, &ba.lox_pub).unwrap(); cred } From 86cd2f54d7d5b907d3c1eaf512825cc0fdc00e43 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Mon, 3 May 2021 14:14:17 -0400 Subject: [PATCH 034/115] More Rust cleanups --- crates/lox-library/src/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 8b3e7d5..27506f0 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -296,7 +296,7 @@ impl BridgeAuth { + cred.invites_issued * self.lox_priv.x[6]) * cred.P; - return Q == cred.Q; + Q == cred.Q } #[cfg(test)] @@ -311,7 +311,8 @@ impl BridgeAuth { + cred.from_bucket * self.migration_priv.x[2] + cred.to_bucket * self.migration_priv.x[3]) * cred.P; - return Q == cred.Q; + + Q == cred.Q } #[cfg(test)] @@ -325,7 +326,8 @@ impl BridgeAuth { + cred.date * self.reachability_priv.x[1] + cred.bucket * self.reachability_priv.x[2]) * cred.P; - return Q == cred.Q; + + Q == cred.Q } } From 088071571a552edee820c01e3bb2b396d09ec479 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Mon, 3 May 2021 14:27:11 -0400 Subject: [PATCH 035/115] Change the invites_issued attribute of the Lox credential to just count blockages instead --- crates/lox-library/src/cred.rs | 2 +- crates/lox-library/src/lib.rs | 2 +- crates/lox-library/src/proto/level_up.rs | 135 +++++++++--------- crates/lox-library/src/proto/migration.rs | 16 +-- crates/lox-library/src/proto/open_invite.rs | 6 +- .../lox-library/src/proto/trust_promotion.rs | 4 +- 6 files changed, 83 insertions(+), 82 deletions(-) diff --git a/crates/lox-library/src/cred.rs b/crates/lox-library/src/cred.rs index 5839f13..205a3f6 100644 --- a/crates/lox-library/src/cred.rs +++ b/crates/lox-library/src/cred.rs @@ -35,7 +35,7 @@ pub struct Lox { pub trust_level: Scalar, pub level_since: Scalar, pub invites_remaining: Scalar, - pub invites_issued: Scalar, + pub blockages: Scalar, } /// The migration key credential. diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 27506f0..5e5d52b 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -293,7 +293,7 @@ impl BridgeAuth { + cred.trust_level * self.lox_priv.x[3] + cred.level_since * self.lox_priv.x[4] + cred.invites_remaining * self.lox_priv.x[5] - + cred.invites_issued * self.lox_priv.x[6]) + + cred.blockages * self.lox_priv.x[6]) * cred.P; Q == cred.Q diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs index f260c0a..1b6d924 100644 --- a/crates/lox-library/src/proto/level_up.rs +++ b/crates/lox-library/src/proto/level_up.rs @@ -15,7 +15,8 @@ The user presents their current Lox credential: - level_since: blinded, but proved in ZK that it's at least the appropriate number of days ago - invites_remaining: blinded -- invites_issued: blinded +- blockages: blinded, but proved in ZK that it's at most the appropriate + blockage limit for the target trust level and a Bucket Reachability credential: - date: revealed to be today @@ -32,7 +33,7 @@ and a new Lox credential to be issued: - invites_remaining: revealed to be the number of invites for the new level (note that the invites_remaining from the previous credential are _not_ carried over) -- invites_issued: blinded, but proved in ZK that it's the same as in the +- blockages: blinded, but proved in ZK that it's the same as in the Lox credential above */ @@ -79,7 +80,7 @@ pub struct Request { level: Scalar, CSince: RistrettoPoint, CInvRemain: RistrettoPoint, - CInvIssued: RistrettoPoint, + CBlockages: RistrettoPoint, CQ: RistrettoPoint, // Fields for blind showing the Bucket Reachability credential @@ -111,7 +112,7 @@ pub struct Request { D: RistrettoPoint, EncIdClient: (RistrettoPoint, RistrettoPoint), EncBucket: (RistrettoPoint, RistrettoPoint), - EncInvIssued: (RistrettoPoint, RistrettoPoint), + EncBlockages: (RistrettoPoint, RistrettoPoint), // The combined ZKP piUser: CompactProof, @@ -123,12 +124,12 @@ pub struct State { D: RistrettoPoint, EncIdClient: (RistrettoPoint, RistrettoPoint), EncBucket: (RistrettoPoint, RistrettoPoint), - EncInvIssued: (RistrettoPoint, RistrettoPoint), + EncBlockages: (RistrettoPoint, RistrettoPoint), id_client: Scalar, bucket: Scalar, level: Scalar, invremain: Scalar, - invissued: Scalar, + blockages: Scalar, } pub struct Response { @@ -141,7 +142,7 @@ pub struct Response { level_since: Scalar, TId: RistrettoPoint, TBucket: RistrettoPoint, - TInvIssued: RistrettoPoint, + TBlockages: RistrettoPoint, // The ZKP piBlindIssue: CompactProof, @@ -150,19 +151,19 @@ pub struct Response { define_proof! { requestproof, "Level Upgrade Request", - (bucket, since, invremain, invissued, zbucket, zsince, zinvremain, - zinvissued, negzQ, + (bucket, since, invremain, blockages, zbucket, zsince, zinvremain, + zblockages, negzQ, zbucket_reach, negzQ_reach, - d, eid_client, ebucket, einvissued, id_client, + d, eid_client, ebucket, eblockages, id_client, g0, g1, g2, g3, g4, g5, g6, g7, g8, zg0, zg1, zg2, zg3, zg4, zg5, zg6, zg7, zg8, wg0, wg1, wg2, wg3, wg4, wg5, wg6, wg7, wg8, yg0, yg1, yg2, yg3, yg4, yg5, yg6, yg7, yg8), - (P, CBucket, CSince, CInvRemain, CInvIssued, V, Xbucket, Xsince, - Xinvremain, Xinvissued, + (P, CBucket, CSince, CInvRemain, CBlockages, V, Xbucket, Xsince, + Xinvremain, Xblockages, P_reach, CBucket_reach, V_reach, Xbucket_reach, D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1, - EncInvIssued0, EncInvIssued1, + EncBlockages0, EncBlockages1, CG0, CG1, CG2, CG3, CG4, CG5, CG6, CG7, CG8, CG0sq, CG1sq, CG2sq, CG3sq, CG4sq, CG5sq, CG6sq, CG7sq, CG8sq), (A, B) : @@ -170,7 +171,7 @@ define_proof! { CBucket = (bucket*P + zbucket*A), CSince = (since*P + zsince*A), CInvRemain = (invremain*P + zinvremain*A), - CInvIssued = (invissued*P + zinvissued*A), + CBlockages = (blockages*P + zblockages*A), // Blind showing of the Bucket Reachability credential; note the // same bucket is used in the proof CBucket_reach = (bucket*P_reach + zbucket_reach*A), @@ -180,8 +181,8 @@ define_proof! { EncIdClient1 = (id_client*B + eid_client*D), EncBucket0 = (ebucket*B), EncBucket1 = (bucket*B + ebucket*D), - EncInvIssued0 = (einvissued*B), - EncInvIssued1 = (invissued*B + einvissued*D), + EncBlockages0 = (eblockages*B), + EncBlockages1 = (blockages*B + eblockages*D), // Prove CSince encodes a value at least LEVEL_INTERVAL // days ago (at technically at most LEVEL_INTERVAL+511 days // ago): first prove each of g0, ..., g8 is a bit by proving that @@ -204,11 +205,11 @@ define_proof! { define_proof! { blindissue, "Level Upgrade Issuing", - (x0, x0tilde, xid, xbucket, xlevel, xsince, xinvremain, xinvissued, - s, b, tid, tbucket, tinvissued), + (x0, x0tilde, xid, xbucket, xlevel, xsince, xinvremain, xblockages, + s, b, tid, tbucket, tblockages), (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xlevel, Xsince, Xinvremain, - Xinvissued, Plevel, Psince, Pinvremain, TId, TBucket, TInvIssued, - D, EncId0, EncId1, EncBucket0, EncBucket1, EncInvIssued0, EncInvIssued1), + Xblockages, Plevel, Psince, Pinvremain, TId, TBucket, TBlockages, + D, EncId0, EncId1, EncBucket0, EncBucket1, EncBlockages0, EncBlockages1), (A, B): Xid = (xid*A), Xid = (xid*A), @@ -216,18 +217,18 @@ define_proof! { Xbucket = (xbucket*A), Xsince = (xsince*A), Xinvremain = (xinvremain*A), - Xinvissued = (xinvissued*A), + Xblockages = (xblockages*A), X0 = (x0*B + x0tilde*A), P = (b*B), TId = (b*Xid), TId = (tid*A), TBucket = (b*Xbucket), TBucket = (tbucket*A), - TInvIssued = (b*Xinvissued), - TInvIssued = (tinvissued*A), - EncQ0 = (s*B + tid*EncId0 + tbucket*EncBucket0 + tinvissued*EncInvIssued0), + TBlockages = (b*Xblockages), + TBlockages = (tblockages*A), + EncQ0 = (s*B + tid*EncId0 + tbucket*EncBucket0 + tblockages*EncBlockages0), EncQ1 = (s*D + tid*EncId1 + tbucket*EncBucket1 - + tinvissued*EncInvIssued1 + x0*P + xlevel*Plevel + xsince*Psince + + tblockages*EncBlockages1 + x0*P + xlevel*Plevel + xsince*Psince + xinvremain*Pinvremain) } @@ -302,11 +303,11 @@ pub fn request( let zbucket = Scalar::random(&mut rng); let zsince = Scalar::random(&mut rng); let zinvremain = Scalar::random(&mut rng); - let zinvissued = Scalar::random(&mut rng); + let zblockages = Scalar::random(&mut rng); let CBucket = lox_cred.bucket * P + &zbucket * Atable; let CSince = lox_cred.level_since * P + &zsince * Atable; let CInvRemain = lox_cred.invites_remaining * P + &zinvremain * Atable; - let CInvIssued = lox_cred.invites_issued * P + &zinvissued * Atable; + let CBlockages = lox_cred.blockages * P + &zblockages * Atable; // Form a Pedersen commitment to the MAC Q // We flip the sign of zQ from that of the Hyphae paper so that @@ -319,7 +320,7 @@ pub fn request( let V = zbucket * lox_pub.X[2] + zsince * lox_pub.X[4] + zinvremain * lox_pub.X[5] - + zinvissued * lox_pub.X[6] + + zblockages * lox_pub.X[6] + &negzQ * Atable; // Blind showing the Bucket Reachability credential @@ -361,10 +362,10 @@ pub fn request( let ebucket = Scalar::random(&mut rng); let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D); let newinvites: Scalar = LEVEL_INVITATIONS[new_level as usize].into(); - let einvissued = Scalar::random(&mut rng); - let EncInvIssued = ( - &einvissued * Btable, - &lox_cred.invites_issued * Btable + einvissued * D, + let eblockages = Scalar::random(&mut rng); + let EncBlockages = ( + &eblockages * Btable, + &lox_cred.blockages * Btable + eblockages * D, ); // The range proof that 0 <= diffdays <= 511 @@ -455,12 +456,12 @@ pub fn request( CBucket: &CBucket, CSince: &CSince, CInvRemain: &CInvRemain, - CInvIssued: &CInvIssued, + CBlockages: &CBlockages, V: &V, Xbucket: &lox_pub.X[2], Xsince: &lox_pub.X[4], Xinvremain: &lox_pub.X[5], - Xinvissued: &lox_pub.X[6], + Xblockages: &lox_pub.X[6], P_reach: &P_reach, CBucket_reach: &CBucket_reach, V_reach: &V_reach, @@ -470,8 +471,8 @@ pub fn request( EncIdClient1: &EncIdClient.1, EncBucket0: &EncBucket.0, EncBucket1: &EncBucket.1, - EncInvIssued0: &EncInvIssued.0, - EncInvIssued1: &EncInvIssued.1, + EncBlockages0: &EncBlockages.0, + EncBlockages1: &EncBlockages.1, CG0: &CG0, CG1: &CG1, CG2: &CG2, @@ -493,18 +494,18 @@ pub fn request( bucket: &lox_cred.bucket, since: &lox_cred.level_since, invremain: &lox_cred.invites_remaining, - invissued: &lox_cred.invites_issued, + blockages: &lox_cred.blockages, zbucket: &zbucket, zsince: &zsince, zinvremain: &zinvremain, - zinvissued: &zinvissued, + zblockages: &zblockages, negzQ: &negzQ, zbucket_reach: &zbucket_reach, negzQ_reach: &negzQ_reach, d: &d, eid_client: &eid_client, ebucket: &ebucket, - einvissued: &einvissued, + eblockages: &eblockages, id_client: &id_client, g0: &g0, g1: &g1, @@ -554,7 +555,7 @@ pub fn request( level: lox_cred.trust_level, CSince, CInvRemain, - CInvIssued, + CBlockages, CQ, P_reach, CBucket_reach, @@ -562,7 +563,7 @@ pub fn request( D, EncIdClient, EncBucket, - EncInvIssued, + EncBlockages, CG1, CG2, CG3, @@ -587,12 +588,12 @@ pub fn request( D, EncIdClient, EncBucket, - EncInvIssued, + EncBlockages, id_client, bucket: lox_cred.bucket, level: new_level.into(), invremain: newinvites, - invissued: lox_cred.invites_issued, + blockages: lox_cred.blockages, }, )) } @@ -626,7 +627,7 @@ impl BridgeAuth { + self.lox_priv.x[2] * req.CBucket + self.lox_priv.x[4] * req.CSince + self.lox_priv.x[5] * req.CInvRemain - + self.lox_priv.x[6] * req.CInvIssued + + self.lox_priv.x[6] * req.CBlockages - req.CQ; let Vprime_reach = (self.reachability_priv.x[0] + self.reachability_priv.x[1] * today) @@ -663,12 +664,12 @@ impl BridgeAuth { CBucket: &req.CBucket.compress(), CSince: &req.CSince.compress(), CInvRemain: &req.CInvRemain.compress(), - CInvIssued: &req.CInvIssued.compress(), + CBlockages: &req.CBlockages.compress(), V: &Vprime.compress(), Xbucket: &self.lox_pub.X[2].compress(), Xsince: &self.lox_pub.X[4].compress(), Xinvremain: &self.lox_pub.X[5].compress(), - Xinvissued: &self.lox_pub.X[6].compress(), + Xblockages: &self.lox_pub.X[6].compress(), P_reach: &req.P_reach.compress(), CBucket_reach: &req.CBucket_reach.compress(), V_reach: &Vprime_reach.compress(), @@ -678,8 +679,8 @@ impl BridgeAuth { EncIdClient1: &req.EncIdClient.1.compress(), EncBucket0: &req.EncBucket.0.compress(), EncBucket1: &req.EncBucket.1.compress(), - EncInvIssued0: &req.EncInvIssued.0.compress(), - EncInvIssued1: &req.EncInvIssued.1.compress(), + EncBlockages0: &req.EncBlockages.0.compress(), + EncBlockages1: &req.EncBlockages.1.compress(), CG0: &CG0prime.compress(), CG1: &req.CG1.compress(), CG2: &req.CG2.compress(), @@ -750,16 +751,16 @@ impl BridgeAuth { let tbucket = self.lox_priv.x[2] * b; let TBucket = &tbucket * Atable; let EncQBucket = (tbucket * req.EncBucket.0, tbucket * req.EncBucket.1); - let tinvissued = self.lox_priv.x[6] * b; - let TInvIssued = &tinvissued * Atable; - let EncQInvIssued = ( - tinvissued * req.EncInvIssued.0, - tinvissued * req.EncInvIssued.1, + let tblockages = self.lox_priv.x[6] * b; + let TBlockages = &tblockages * Atable; + let EncQBlockages = ( + tblockages * req.EncBlockages.0, + tblockages * req.EncBlockages.1, ); let EncQ = ( - EncQHc.0 + EncQId.0 + EncQBucket.0 + EncQInvIssued.0, - EncQHc.1 + EncQId.1 + EncQBucket.1 + EncQInvIssued.1, + EncQHc.0 + EncQId.0 + EncQBucket.0 + EncQBlockages.0, + EncQHc.1 + EncQId.1 + EncQBucket.1 + EncQBlockages.1, ); let mut transcript = Transcript::new(b"level upgrade issuing"); @@ -777,20 +778,20 @@ impl BridgeAuth { Xlevel: &self.lox_pub.X[3], Xsince: &self.lox_pub.X[4], Xinvremain: &self.lox_pub.X[5], - Xinvissued: &self.lox_pub.X[6], + Xblockages: &self.lox_pub.X[6], Plevel: &(trust_level * P), Psince: &(level_since * P), Pinvremain: &(invitations_remaining * P), TId: &TId, TBucket: &TBucket, - TInvIssued: &TInvIssued, + TBlockages: &TBlockages, D: &req.D, EncId0: &EncId.0, EncId1: &EncId.1, EncBucket0: &req.EncBucket.0, EncBucket1: &req.EncBucket.1, - EncInvIssued0: &req.EncInvIssued.0, - EncInvIssued1: &req.EncInvIssued.1, + EncBlockages0: &req.EncBlockages.0, + EncBlockages1: &req.EncBlockages.1, x0: &self.lox_priv.x[0], x0tilde: &self.lox_priv.x0tilde, xid: &self.lox_priv.x[1], @@ -798,12 +799,12 @@ impl BridgeAuth { xlevel: &self.lox_priv.x[3], xsince: &self.lox_priv.x[4], xinvremain: &self.lox_priv.x[5], - xinvissued: &self.lox_priv.x[6], + xblockages: &self.lox_priv.x[6], s: &s, b: &b, tid: &tid, tbucket: &tbucket, - tinvissued: &tinvissued, + tblockages: &tblockages, }, ) .0; @@ -815,7 +816,7 @@ impl BridgeAuth { level_since, TId, TBucket, - TInvIssued, + TBlockages, piBlindIssue, }) } @@ -861,20 +862,20 @@ pub fn handle_response( Xlevel: &lox_pub.X[3].compress(), Xsince: &lox_pub.X[4].compress(), Xinvremain: &lox_pub.X[5].compress(), - Xinvissued: &lox_pub.X[6].compress(), + Xblockages: &lox_pub.X[6].compress(), Plevel: &(state.level * resp.P).compress(), Psince: &(resp.level_since * resp.P).compress(), Pinvremain: &(state.invremain * resp.P).compress(), TId: &resp.TId.compress(), TBucket: &resp.TBucket.compress(), - TInvIssued: &resp.TInvIssued.compress(), + TBlockages: &resp.TBlockages.compress(), D: &state.D.compress(), EncId0: &EncId.0.compress(), EncId1: &EncId.1.compress(), EncBucket0: &state.EncBucket.0.compress(), EncBucket1: &state.EncBucket.1.compress(), - EncInvIssued0: &state.EncInvIssued.0.compress(), - EncInvIssued1: &state.EncInvIssued.1.compress(), + EncBlockages0: &state.EncBlockages.0.compress(), + EncBlockages1: &state.EncBlockages.1.compress(), }, )?; @@ -889,6 +890,6 @@ pub fn handle_response( trust_level: state.level, level_since: resp.level_since, invites_remaining: state.invremain, - invites_issued: state.invissued, + blockages: state.blockages, }) } diff --git a/crates/lox-library/src/proto/migration.rs b/crates/lox-library/src/proto/migration.rs index b20badb..0402f8a 100644 --- a/crates/lox-library/src/proto/migration.rs +++ b/crates/lox-library/src/proto/migration.rs @@ -10,7 +10,7 @@ Lox credential: - trust_level: revealed to be 0 - level_since: blinded - invites_remaining: revealed to be 0 -- invites_issued: revealed to be 0 +- blockages: revealed to be 0 and a Migration credential: @@ -27,7 +27,7 @@ and a new Lox credential to be issued: - trust_level: 1 - level_since: today - invites_remaining: 0 -- invites_issued: 0 +- blockages: 0 */ @@ -47,7 +47,7 @@ use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; pub struct Request { // Fields for blind showing the Lox credential - // We don't need to include invites_remaining or invites_issued, + // We don't need to include invites_remaining or blockages, // since they must be 0 P_lox: RistrettoPoint, id: Scalar, @@ -390,14 +390,14 @@ impl BridgeAuth { // Julian date let level_since: Scalar = self.today().into(); - // The invitations_remaining and invitations_issued attributes - // are 0 for level 0 and level 1 Lox credentials, so we don't - // need to explicitly create them. + // The invitations_remaining and blockages attributes are 0 for + // level 0 and level 1 Lox credentials, so we don't need to + // explicitly create them. // Compute the MAC on the visible attributes let b = Scalar::random(&mut rng); let P = &b * Btable; - // invites_remaining = invites_issued = 0 + // invites_remaining = blockages = 0 let QHc = (self.lox_priv.x[0] + self.lox_priv.x[3] * trust_level + self.lox_priv.x[4] * level_since) @@ -533,6 +533,6 @@ pub fn handle_response( trust_level: Scalar::one(), level_since: resp.level_since, invites_remaining: Scalar::zero(), - invites_issued: Scalar::zero(), + blockages: Scalar::zero(), }) } diff --git a/crates/lox-library/src/proto/open_invite.rs b/crates/lox-library/src/proto/open_invite.rs index 7754541..d2ee731 100644 --- a/crates/lox-library/src/proto/open_invite.rs +++ b/crates/lox-library/src/proto/open_invite.rs @@ -9,7 +9,7 @@ The credential will have attributes: - trust_level: 0 - level_since: today - invites_remaining: 0 -- invites_issued: 0 +- blockages: 0 */ @@ -197,7 +197,7 @@ impl BridgeAuth { // Compute the MAC on the visible attributes let b = Scalar::random(&mut rng); let P = &b * Btable; - // trust_level = invites_remaining = invites_issued = 0 + // trust_level = invites_remaining = blockages = 0 let QHc = (self.lox_priv.x[0] + self.lox_priv.x[2] * bucket + self.lox_priv.x[4] * level_since) * P; @@ -315,6 +315,6 @@ pub fn handle_response( trust_level: Scalar::zero(), level_since: resp.level_since, invites_remaining: Scalar::zero(), - invites_issued: Scalar::zero(), + blockages: Scalar::zero(), }) } diff --git a/crates/lox-library/src/proto/trust_promotion.rs b/crates/lox-library/src/proto/trust_promotion.rs index 578e584..92a68c9 100644 --- a/crates/lox-library/src/proto/trust_promotion.rs +++ b/crates/lox-library/src/proto/trust_promotion.rs @@ -14,7 +14,7 @@ The user presents their current Lox credential: - level_since: blinded, but proved in ZK that it's at least UNTRUSTED_INTERVAL days ago - invites_remaining: revealed to be 0 -- invites_issued: revealed to be 0 +- blockages: revealed to be 0 They will receive in return the encrypted MAC (Pk, EncQk) for their implicit Migration Key credential with attributes id and bucket, @@ -57,7 +57,7 @@ pub const UNTRUSTED_INTERVAL: u32 = 30; pub struct Request { // Fields for blind showing the Lox credential // We don't need to include trust_level, invites_remaining, or - // invites_issued, since they must be 0 + // blockages, since they must be 0 P: RistrettoPoint, id: Scalar, CBucket: RistrettoPoint, From 654208769fbfb148321140841e74f08b8798c988 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Mon, 3 May 2021 14:59:55 -0400 Subject: [PATCH 036/115] Up the max level to 4 and add the ZKP for the max number of blockages allowed in the level up protocol --- crates/lox-library/src/proto/level_up.rs | 120 ++++++++++++++++-- .../lox-library/src/proto/trust_promotion.rs | 2 +- 2 files changed, 112 insertions(+), 10 deletions(-) diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs index 1b6d924..9eafe96 100644 --- a/crates/lox-library/src/proto/level_up.rs +++ b/crates/lox-library/src/proto/level_up.rs @@ -57,20 +57,26 @@ use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; /// upgrade protocol when they're already at the max level; they will /// get a fresh invites_remaining batch, and reset their level_since /// field to today's date, but will remain in the max level. -pub const MAX_LEVEL: usize = 3; +pub const MAX_LEVEL: usize = 4; /// LEVEL_INTERVAL\[i\] for i >= 1 is the minimum number of days a user /// must be at trust level i before advancing to level i+1 (or as above, /// remain at level i if i == MAX_LEVEL). Note that the /// LEVEL_INTERVAL\[0\] entry is a dummy; the trust_promotion protocol /// is used instead of this one to move from level 0 to level 1. -pub const LEVEL_INTERVAL: [u32; MAX_LEVEL + 1] = [0, 14, 28, 56]; +pub const LEVEL_INTERVAL: [u32; MAX_LEVEL + 1] = [0, 14, 28, 56, 84]; /// LEVEL_INVITATIONS\[i\] for i >= 1 is the number of invitations a /// user will be eligible to issue upon advancing from level i to level /// i+1. Again the LEVEL_INVITATIONS\[0\] entry is a dummy, as for /// LEVEL_INTERVAL. -pub const LEVEL_INVITATIONS: [u32; MAX_LEVEL + 1] = [0, 2, 4, 6]; +pub const LEVEL_INVITATIONS: [u32; MAX_LEVEL + 1] = [0, 2, 4, 6, 8]; + +/// MAX_BLOCKAGES\[i\] for i >= 1 is the maximum number of bucket +/// blockages this credential is allowed to have recorded in order to +/// advance from level i to level i+1. Again the LEVEL_INVITATIONS\[0\] +/// entry is a dummy, as for LEVEL_INTERVAL. +pub const MAX_BLOCKAGES: [u32; MAX_LEVEL + 1] = [0, 4, 3, 2, 2]; pub struct Request { // Fields for blind showing the Lox credential @@ -88,8 +94,8 @@ pub struct Request { CBucket_reach: RistrettoPoint, CQ_reach: RistrettoPoint, - // Fields for the inequality proof (level_since + - // LEVEL_INTERVAL[level] <= today) + // Fields for the inequality proof + // level_since + LEVEL_INTERVAL[level] <= today CG1: RistrettoPoint, CG2: RistrettoPoint, CG3: RistrettoPoint, @@ -108,6 +114,14 @@ pub struct Request { CG7sq: RistrettoPoint, CG8sq: RistrettoPoint, + // Fields for the inequality proof + // blockages <= MAX_BLOCKAGES[level] + CH1: RistrettoPoint, + CH2: RistrettoPoint, + CH0sq: RistrettoPoint, + CH1sq: RistrettoPoint, + CH2sq: RistrettoPoint, + // Fields for user blinding of the Lox credential to be issued D: RistrettoPoint, EncIdClient: (RistrettoPoint, RistrettoPoint), @@ -158,14 +172,20 @@ define_proof! { g0, g1, g2, g3, g4, g5, g6, g7, g8, zg0, zg1, zg2, zg3, zg4, zg5, zg6, zg7, zg8, wg0, wg1, wg2, wg3, wg4, wg5, wg6, wg7, wg8, - yg0, yg1, yg2, yg3, yg4, yg5, yg6, yg7, yg8), + yg0, yg1, yg2, yg3, yg4, yg5, yg6, yg7, yg8, + h0, h1, h2, + zh0, zh1, zh2, + wh0, wh1, wh2, + yh0, yh1, yh2), (P, CBucket, CSince, CInvRemain, CBlockages, V, Xbucket, Xsince, Xinvremain, Xblockages, P_reach, CBucket_reach, V_reach, Xbucket_reach, D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1, EncBlockages0, EncBlockages1, CG0, CG1, CG2, CG3, CG4, CG5, CG6, CG7, CG8, - CG0sq, CG1sq, CG2sq, CG3sq, CG4sq, CG5sq, CG6sq, CG7sq, CG8sq), + CG0sq, CG1sq, CG2sq, CG3sq, CG4sq, CG5sq, CG6sq, CG7sq, CG8sq, + CH0, CH1, CH2, + CH0sq, CH1sq, CH2sq), (A, B) : // Blind showing of the Lox credential CBucket = (bucket*P + zbucket*A), @@ -184,7 +204,7 @@ define_proof! { EncBlockages0 = (eblockages*B), EncBlockages1 = (blockages*B + eblockages*D), // Prove CSince encodes a value at least LEVEL_INTERVAL - // days ago (at technically at most LEVEL_INTERVAL+511 days + // days ago (and technically at most LEVEL_INTERVAL+511 days // ago): first prove each of g0, ..., g8 is a bit by proving that // gi = gi^2 CG0 = (g0*P + zg0*A), CG0sq = (g0*CG0 + wg0*A), CG0sq = (g0*P + yg0*A), @@ -195,11 +215,20 @@ define_proof! { CG5 = (g5*P + zg5*A), CG5sq = (g5*CG5 + wg5*A), CG5sq = (g5*P + yg5*A), CG6 = (g6*P + zg6*A), CG6sq = (g6*CG6 + wg6*A), CG6sq = (g6*P + yg6*A), CG7 = (g7*P + zg7*A), CG7sq = (g7*CG7 + wg7*A), CG7sq = (g7*P + yg7*A), - CG8 = (g8*P + zg8*A), CG8sq = (g8*CG8 + wg8*A), CG8sq = (g8*P + yg8*A) + CG8 = (g8*P + zg8*A), CG8sq = (g8*CG8 + wg8*A), CG8sq = (g8*P + yg8*A), // Then we'll check that CSince + LEVEL_INTERVAL*P + CG0 + 2*CG1 // + 4*CG2 + 8*CG3 + ... + 256*CG8 = today*P by having the verifier // plug in today*P - (CSince + LEVEL_INTERVAL*P + 2*CG1 + 4*CG2 // + ... + 256*CG8) as its value of CG0. + + // Prove CBlockage encodes a value at most MAX_BLOCKAGES (and at least + // MAX_BLOCKAGES-7) + CH0 = (h0*P + zh0*A), CH0sq = (h0*CH0 + wh0*A), CH0sq = (h0*P + yh0*A), + CH1 = (h1*P + zh1*A), CH1sq = (h1*CH1 + wh1*A), CH1sq = (h1*P + yh1*A), + CH2 = (h2*P + zh2*A), CH2sq = (h2*CH2 + wh2*A), CH2sq = (h2*P + yh2*A) + // Then we'll check that CBlockage + CH0 + 2*CH1 + 4*CH2 = + // MAX_BLOCKAGES*P by having the verifier plug in MAX_BLOCKAGES*P - + // (CBlockage - 2*CH1 - 4*CH2) as its value of CH0. } define_proof! { @@ -271,6 +300,15 @@ pub fn request( if diffdays > 511 { return Err(ProofError::VerificationFailure); } + // The current number of blockages + let blockages: u32 = match scalar_u32(&lox_cred.blockages) { + Some(v) => v, + None => return Err(ProofError::VerificationFailure), + }; + if blockages > MAX_BLOCKAGES[trust_level as usize] { + return Err(ProofError::VerificationFailure); + } + let blockage_diff = MAX_BLOCKAGES[trust_level as usize] - blockages; // The buckets in the Lox and Bucket Reachability credentials have // to match if lox_cred.bucket != reach_cred.bucket { @@ -445,6 +483,37 @@ pub fn request( let CG7sq = g7 * P + &yg7 * Atable; let CG8sq = g8 * P + &yg8 * Atable; + // The range proof that 0 <= blockage_diff <= 7 + + // Extract the 3 bits from blockage_diff + let h0: Scalar = (blockage_diff & 1).into(); + let h1: Scalar = ((blockage_diff >> 1) & 1).into(); + let h2: Scalar = ((blockage_diff >> 2) & 1).into(); + + // Pick random factors for the Pedersen commitments + let wh0 = Scalar::random(&mut rng); + let zh1 = Scalar::random(&mut rng); + let wh1 = Scalar::random(&mut rng); + let zh2 = Scalar::random(&mut rng); + let wh2 = Scalar::random(&mut rng); + + // Compute zh0 to cancel things out as + // zh0 = -(zblockages + 2*zh1 + 4*zh2) + // but use Horner's method + let zh0 = -(scalar_dbl(&(scalar_dbl(&zh2) + zh1)) + zblockages); + + let yh0 = wh0 + h0 * zh0; + let yh1 = wh1 + h1 * zh1; + let yh2 = wh2 + h2 * zh2; + + let CH0 = h0 * P + &zh0 * Atable; + let CH1 = h1 * P + &zh1 * Atable; + let CH2 = h2 * P + &zh2 * Atable; + + let CH0sq = h0 * P + &yh0 * Atable; + let CH1sq = h1 * P + &yh1 * Atable; + let CH2sq = h2 * P + &yh2 * Atable; + // Construct the proof let mut transcript = Transcript::new(b"level upgrade request"); let piUser = requestproof::prove_compact( @@ -491,6 +560,12 @@ pub fn request( CG6sq: &CG6sq, CG7sq: &CG7sq, CG8sq: &CG8sq, + CH0: &CH0, + CH1: &CH1, + CH2: &CH2, + CH0sq: &CH0sq, + CH1sq: &CH1sq, + CH2sq: &CH2sq, bucket: &lox_cred.bucket, since: &lox_cred.level_since, invremain: &lox_cred.invites_remaining, @@ -543,6 +618,18 @@ pub fn request( yg6: &yg6, yg7: &yg7, yg8: &yg8, + h0: &h0, + h1: &h1, + h2: &h2, + zh0: &zh0, + zh1: &zh1, + zh2: &zh2, + wh0: &wh0, + wh1: &wh1, + wh2: &wh2, + yh0: &yh0, + yh1: &yh1, + yh2: &yh2, }, ) .0; @@ -581,6 +668,11 @@ pub fn request( CG6sq, CG7sq, CG8sq, + CH1, + CH2, + CH0sq, + CH1sq, + CH2sq, piUser, }, State { @@ -652,6 +744,10 @@ impl BridgeAuth { ) + req.CG1), ); + // Recompute CH0 using Horner's method + let mblk: Scalar = MAX_BLOCKAGES[level].into(); + let CH0prime = mblk * req.P - req.CBlockages - pt_dbl(&(pt_dbl(&req.CH2) + req.CH1)); + // Verify the ZKP let mut transcript = Transcript::new(b"level upgrade request"); requestproof::verify_compact( @@ -699,6 +795,12 @@ impl BridgeAuth { CG6sq: &req.CG6sq.compress(), CG7sq: &req.CG7sq.compress(), CG8sq: &req.CG8sq.compress(), + CH0: &CH0prime.compress(), + CH1: &req.CH1.compress(), + CH2: &req.CH2.compress(), + CH0sq: &req.CH0sq.compress(), + CH1sq: &req.CH1sq.compress(), + CH2sq: &req.CH2sq.compress(), }, )?; diff --git a/crates/lox-library/src/proto/trust_promotion.rs b/crates/lox-library/src/proto/trust_promotion.rs index 92a68c9..81ebab8 100644 --- a/crates/lox-library/src/proto/trust_promotion.rs +++ b/crates/lox-library/src/proto/trust_promotion.rs @@ -136,7 +136,7 @@ define_proof! { EncBucket1 = (bucket*B + ebucket*D), D = (d*B), // Prove CSince encodes a value at least UNTRUSTED_INTERVAL - // days ago (at technically at most UNTRUSTED_INTERVAL+511 days + // days ago (and technically at most UNTRUSTED_INTERVAL+511 days // ago): first prove each of g0, ..., g8 is a bit by proving that // gi = gi^2 CG0 = (g0*P + zg0*A), CG0sq = (g0*CG0 + wg0*A), CG0sq = (g0*P + yg0*A), From d924b98060c6e803461f878e17e4d88039917a2e Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Mon, 3 May 2021 19:05:42 -0400 Subject: [PATCH 037/115] The request message of the issue invitation protocol --- crates/lox-library/src/cred.rs | 18 + crates/lox-library/src/lib.rs | 26 ++ crates/lox-library/src/proto/issue_invite.rs | 443 +++++++++++++++++++ crates/lox-library/src/proto/level_up.rs | 6 +- crates/lox-library/src/tests.rs | 32 ++ 5 files changed, 523 insertions(+), 2 deletions(-) create mode 100644 crates/lox-library/src/proto/issue_invite.rs diff --git a/crates/lox-library/src/cred.rs b/crates/lox-library/src/cred.rs index 205a3f6..b070854 100644 --- a/crates/lox-library/src/cred.rs +++ b/crates/lox-library/src/cred.rs @@ -75,3 +75,21 @@ pub struct BucketReachability { pub date: Scalar, pub bucket: Scalar, } + +/// The Invitation credential. +/// +/// 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_ +/// 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. +#[derive(Debug)] +pub struct Invitation { + pub P: RistrettoPoint, + pub Q: RistrettoPoint, + pub inv_id: Scalar, + pub date: Scalar, + pub bucket: Scalar, + pub blockages: Scalar, +} diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 5e5d52b..2fbf9b0 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -190,6 +190,10 @@ pub struct BridgeAuth { reachability_priv: IssuerPrivKey, /// The public key for bucket reachability credentials pub reachability_pub: IssuerPubKey, + /// The private key for invitation credentials + invitation_priv: IssuerPrivKey, + /// The public key for invitation credentials + pub invitation_pub: IssuerPubKey, /// The public key of the BridgeDb issuing open invitations pub bridgedb_pub: PublicKey, @@ -224,6 +228,8 @@ impl BridgeAuth { let migrationkey_pub = IssuerPubKey::new(&migrationkey_priv); let reachability_priv = IssuerPrivKey::new(2); let reachability_pub = IssuerPubKey::new(&reachability_priv); + let invitation_priv = IssuerPrivKey::new(4); + let invitation_pub = IssuerPubKey::new(&invitation_priv); Self { lox_priv, lox_pub, @@ -233,6 +239,8 @@ impl BridgeAuth { migrationkey_pub, reachability_priv, reachability_pub, + invitation_priv, + invitation_pub, bridgedb_pub, bridge_table: Default::default(), migration_table: Default::default(), @@ -329,6 +337,23 @@ impl BridgeAuth { Q == cred.Q } + + #[cfg(test)] + /// Verify the MAC on a Invitation credential + pub fn verify_invitation(&self, cred: &cred::Invitation) -> bool { + if cred.P.is_identity() { + return false; + } + + let Q = (self.invitation_priv.x[0] + + cred.inv_id * self.invitation_priv.x[1] + + cred.date * self.invitation_priv.x[2] + + cred.bucket * self.invitation_priv.x[3] + + cred.blockages * self.invitation_priv.x[4]) + * cred.P; + + Q == cred.Q + } } /// Try to extract a u64 from a Scalar @@ -372,6 +397,7 @@ pub fn pt_dbl(P: &RistrettoPoint) -> RistrettoPoint { /// Response. It also adds a handle_* function to the BridgeAuth struct /// that consumes a Request and produces a Result. pub mod proto { + pub mod issue_invite; pub mod level_up; pub mod migration; pub mod open_invite; diff --git a/crates/lox-library/src/proto/issue_invite.rs b/crates/lox-library/src/proto/issue_invite.rs new file mode 100644 index 0000000..bee4bc9 --- /dev/null +++ b/crates/lox-library/src/proto/issue_invite.rs @@ -0,0 +1,443 @@ +/*! A module for the protocol for a user to request the issuing of an +Invitation credential they can pass to someone they know. + +They are allowed to do this as long as their current Lox credentials has +a non-zero "invites_remaining" attribute (which will be decreased by +one), and they have a Bucket Reachability credential for their current +bucket and today's date. (Such credentials are placed daily in the +encrypted bridge table.) + +The user presents their current Lox credential: +- id: revealed +- bucket: blinded +- trust_level: blinded +- level_since: blinded +- invites_remaining: blinded, but proved in ZK that it's not zero +- blockages: blinded + +and a Bucket Reachability credential: +- date: revealed to be today +- bucket: blinded, but proved in ZK that it's the same as in the Lox + credential above + +and a new Lox credential to be issued: + +- id: jointly chosen by the user and BA +- bucket: blinded, but proved in ZK that it's the same as in the Lox + credential above +- trust_level: blinded, but proved in ZK that it's the same as in the + Lox credential above +- level_since: blinded, but proved in ZK that it's the same as in the + Lox credential above +- invites_remaining: blinded, but proved in ZK that it's one less than + the number in the Lox credential above +- blockages: blinded, but proved in ZK that it's the same as in the + Lox credential above + +and a new Invitation credential to be issued: + +- inv_id: jointly chosen by the user and BA +- date: revealed to be today +- bucket: blinded, but proved in ZK that it's the same as in the Lox + credential above +- blockages: blinded, but proved in ZK that it's the same as in the Lox + credential above + +*/ + +use curve25519_dalek::ristretto::RistrettoBasepointTable; +use curve25519_dalek::ristretto::RistrettoPoint; +use curve25519_dalek::scalar::Scalar; +use curve25519_dalek::traits::IsIdentity; + +use zkp::CompactProof; +use zkp::ProofError; +use zkp::Transcript; + +use super::super::cred; +use super::super::dup_filter::SeenType; +use super::super::{pt_dbl, scalar_dbl, scalar_u32}; +use super::super::{BridgeAuth, IssuerPubKey}; +use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; + +pub struct Request { + // Fields for blind showing the Lox credential + P: RistrettoPoint, + id: Scalar, + CBucket: RistrettoPoint, + CLevel: RistrettoPoint, + CSince: RistrettoPoint, + CInvRemain: RistrettoPoint, + CBlockages: RistrettoPoint, + CQ: RistrettoPoint, + + // Fields for blind showing the Bucket Reachability credential + P_reach: RistrettoPoint, + CBucket_reach: RistrettoPoint, + CQ_reach: RistrettoPoint, + + // Fields for user blinding of the Lox credential to be issued + D: RistrettoPoint, + EncIdClient: (RistrettoPoint, RistrettoPoint), + EncBucket: (RistrettoPoint, RistrettoPoint), + EncLevel: (RistrettoPoint, RistrettoPoint), + EncSince: (RistrettoPoint, RistrettoPoint), + EncInvRemain: (RistrettoPoint, RistrettoPoint), + EncBlockages: (RistrettoPoint, RistrettoPoint), + + // Fields for user blinding of the Inivtation credential to be + // issued + EncInvIdClient: (RistrettoPoint, RistrettoPoint), + // The bucket and blockages attributes in the Invitation credential + // issuing protocol can just reuse the exact encryptions as for the + // Lox credential issuing protocol above. + + // The combined ZKP + piUser: CompactProof, +} + +#[derive(Debug)] +pub struct State { + d: Scalar, + D: RistrettoPoint, + EncIdClient: (RistrettoPoint, RistrettoPoint), + EncBucket: (RistrettoPoint, RistrettoPoint), + EncLevel: (RistrettoPoint, RistrettoPoint), + EncSince: (RistrettoPoint, RistrettoPoint), + EncInvRemain: (RistrettoPoint, RistrettoPoint), + EncBlockages: (RistrettoPoint, RistrettoPoint), + EncInvIdClient: (RistrettoPoint, RistrettoPoint), + id_client: Scalar, + bucket: Scalar, + level: Scalar, + since: Scalar, + invremain: Scalar, + blockages: Scalar, + inv_id_client: Scalar, +} + +pub struct Response { + // The fields for the new Lox credential; the new invites_remaining + // is one less than the old value, so we don't have to include it + // here explicitly + P: RistrettoPoint, + EncQ: (RistrettoPoint, RistrettoPoint), + id_server: Scalar, + TId: RistrettoPoint, + TBucket: RistrettoPoint, + TLevel: RistrettoPoint, + TSince: RistrettoPoint, + TInvRemain: RistrettoPoint, + TBlockages: RistrettoPoint, + inv_id_server: Scalar, + TInvId: RistrettoPoint, + + // The ZKP + piBlindIssue: CompactProof, +} + +define_proof! { + requestproof, + "Issue Invite Request", + (bucket, level, since, invremain, blockages, zbucket, zlevel, + zsince, zinvremain, zblockages, negzQ, + zbucket_reach, negzQ_reach, + d, eid_client, ebucket, elevel, esince, einvremain, eblockages, id_client, + inv_id_client, einv_id_client, + invremain_inverse, zinvremain_inverse), + (P, CBucket, CLevel, CSince, CInvRemain, CBlockages, V, Xbucket, + Xlevel, Xsince, Xinvremain, Xblockages, + P_reach, CBucket_reach, V_reach, Xbucket_reach, + D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1, + EncLevel0, EncLevel1, EncSince0, EncSince1, + EncInvRemain0, EncInvRemain1_plus_B, EncBlockages0, EncBlockages1, + EncInvIdClient0, EncInvIdClient1), + (A, B): + // Blind showing of the Lox credential + CBucket = (bucket*P + zbucket*A), + CLevel = (level*P + zlevel*A), + CSince = (since*P + zsince*A), + CInvRemain = (invremain*P + zinvremain*A), + CBlockages = (blockages*P + zblockages*A), + // Proof that invremain is not 0 + P = (invremain_inverse*CInvRemain + zinvremain_inverse*A), + // Blind showing of the Bucket Reachability credential; note the + // same bucket is used in the proof + CBucket_reach = (bucket*P_reach + zbucket_reach*A), + // User blinding of the Lox credential to be issued + D = (d*B), + EncIdClient0 = (eid_client*B), + EncIdClient1 = (id_client*B + eid_client*D), + EncBucket0 = (ebucket*B), + EncBucket1 = (bucket*B + ebucket*D), + EncLevel0 = (elevel*B), + EncLevel1 = (level*B + elevel*D), + EncSince0 = (esince*B), + EncSince1 = (since*B + esince*D), + EncInvRemain0 = (einvremain*B), + EncInvRemain1_plus_B = (invremain*B + einvremain*D), + EncBlockages0 = (eblockages*B), + EncBlockages1 = (blockages*B + eblockages*D), + // User blinding of the Invitation to be issued + EncInvIdClient0 = (einv_id_client*B), + EncInvIdClient1 = (inv_id_client*B + einv_id_client*D) +} + +pub fn request( + lox_cred: &cred::Lox, + reach_cred: &cred::BucketReachability, + lox_pub: &IssuerPubKey, + reach_pub: &IssuerPubKey, + today: u32, +) -> Result<(Request, State), ProofError> { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + // Ensure the credential can be correctly shown: it must be the case + // that invites_remaining not be 0 + if lox_cred.invites_remaining == Scalar::zero() { + return Err(ProofError::VerificationFailure); + } + // The buckets in the Lox and Bucket Reachability credentials have + // to match + if lox_cred.bucket != reach_cred.bucket { + return Err(ProofError::VerificationFailure); + } + // The Bucket Reachability credential has to be dated today + let reach_date: u32 = match scalar_u32(&reach_cred.date) { + Some(v) => v, + None => return Err(ProofError::VerificationFailure), + }; + if reach_date != today { + return Err(ProofError::VerificationFailure); + } + // The new invites_remaining + let new_invites_remaining = &lox_cred.invites_remaining - Scalar::one(); + + // Blind showing the Lox credential + + // Reblind P and Q + let mut rng = rand::thread_rng(); + let t = Scalar::random(&mut rng); + let P = t * lox_cred.P; + let Q = t * lox_cred.Q; + + // Form Pedersen commitments to the blinded attributes + let zbucket = Scalar::random(&mut rng); + let zlevel = Scalar::random(&mut rng); + let zsince = Scalar::random(&mut rng); + let zinvremain = Scalar::random(&mut rng); + let zblockages = Scalar::random(&mut rng); + let CBucket = lox_cred.bucket * P + &zbucket * Atable; + let CLevel = lox_cred.bucket * P + &zlevel * Atable; + let CSince = lox_cred.level_since * P + &zsince * Atable; + let CInvRemain = lox_cred.invites_remaining * P + &zinvremain * Atable; + let CBlockages = lox_cred.blockages * P + &zblockages * Atable; + + // Form a Pedersen commitment to the MAC Q + // We flip the sign of zQ from that of the Hyphae paper so that + // the ZKP has a "+" instead of a "-", as that's what the zkp + // macro supports. + let negzQ = Scalar::random(&mut rng); + let CQ = Q - &negzQ * Atable; + + // Compute the "error factor" + let V = zbucket * lox_pub.X[2] + + zlevel * lox_pub.X[3] + + zsince * lox_pub.X[4] + + zinvremain * lox_pub.X[5] + + zblockages * lox_pub.X[6] + + &negzQ * Atable; + + // Blind showing the Bucket Reachability credential + + // Reblind P and Q + let t_reach = Scalar::random(&mut rng); + let P_reach = t_reach * reach_cred.P; + let Q_reach = t_reach * reach_cred.Q; + + // Form Pedersen commitments to the blinded attributes + let zbucket_reach = Scalar::random(&mut rng); + let CBucket_reach = reach_cred.bucket * P_reach + &zbucket_reach * Atable; + + // Form a Pedersen commitment to the MAC Q + // We flip the sign of zQ from that of the Hyphae paper so that + // the ZKP has a "+" instead of a "-", as that's what the zkp + // macro supports. + let negzQ_reach = Scalar::random(&mut rng); + let CQ_reach = Q_reach - &negzQ_reach * Atable; + + // Compute the "error factor" + let V_reach = zbucket_reach * reach_pub.X[2] + &negzQ_reach * Atable; + + // User blinding for the Lox certificate to be issued + + // Pick an ElGamal keypair + let d = Scalar::random(&mut rng); + let D = &d * Btable; + + // Pick a random client component of the id + let id_client = Scalar::random(&mut rng); + + // Encrypt it (times the basepoint B) to the ElGamal public key D we + // just created + let eid_client = Scalar::random(&mut rng); + let EncIdClient = (&eid_client * Btable, &id_client * Btable + eid_client * D); + + // Encrypt the other blinded fields (times B) to D as well + let ebucket = Scalar::random(&mut rng); + let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D); + let elevel = Scalar::random(&mut rng); + let EncLevel = ( + &elevel * Btable, + &lox_cred.trust_level * Btable + elevel * D, + ); + let esince = Scalar::random(&mut rng); + let EncSince = ( + &esince * Btable, + &lox_cred.level_since * Btable + esince * D, + ); + let einvremain = Scalar::random(&mut rng); + let EncInvRemain = ( + &einvremain * Btable, + &new_invites_remaining * Btable + einvremain * D, + ); + let eblockages = Scalar::random(&mut rng); + let EncBlockages = ( + &eblockages * Btable, + &lox_cred.blockages * Btable + eblockages * D, + ); + + // User blinding for the Invitation certificate to be issued + + // Pick a random client component of the id + let inv_id_client = Scalar::random(&mut rng); + + // Encrypt it (times the basepoint B) to the ElGamal public key D we + // just created + let einv_id_client = Scalar::random(&mut rng); + let EncInvIdClient = ( + &einv_id_client * Btable, + &id_client * Btable + einv_id_client * D, + ); + + // The proof that invites_remaining is not zero. We prove this by + // demonstrating that we know its inverse. + let invremain_inverse = &lox_cred.invites_remaining.invert(); + + let zinvremain_inverse = -zinvremain * invremain_inverse; + + // So now invremain_inverse * CInvRemain + zinvremain_inverse * A = P + + // Construct the proof + let mut transcript = Transcript::new(b"issue invite request"); + let piUser = requestproof::prove_compact( + &mut transcript, + requestproof::ProveAssignments { + A: &A, + B: &B, + P: &P, + CBucket: &CBucket, + CLevel: &CLevel, + CSince: &CSince, + CInvRemain: &CInvRemain, + CBlockages: &CBlockages, + V: &V, + Xbucket: &lox_pub.X[2], + Xlevel: &lox_pub.X[3], + Xsince: &lox_pub.X[4], + Xinvremain: &lox_pub.X[5], + Xblockages: &lox_pub.X[6], + P_reach: &P_reach, + CBucket_reach: &CBucket_reach, + V_reach: &V_reach, + Xbucket_reach: &reach_pub.X[2], + D: &D, + EncIdClient0: &EncIdClient.0, + EncIdClient1: &EncIdClient.1, + EncBucket0: &EncBucket.0, + EncBucket1: &EncBucket.1, + EncLevel0: &EncLevel.0, + EncLevel1: &EncLevel.1, + EncSince0: &EncSince.0, + EncSince1: &EncSince.1, + EncInvRemain0: &EncInvRemain.0, + EncInvRemain1_plus_B: &(EncInvRemain.1 + B), + EncBlockages0: &EncBlockages.0, + EncBlockages1: &EncBlockages.1, + EncInvIdClient0: &EncInvIdClient.0, + EncInvIdClient1: &EncInvIdClient.1, + bucket: &lox_cred.bucket, + level: &lox_cred.trust_level, + since: &lox_cred.level_since, + invremain: &lox_cred.invites_remaining, + blockages: &lox_cred.blockages, + zbucket: &zbucket, + zlevel: &zlevel, + zsince: &zsince, + zinvremain: &zinvremain, + zblockages: &zblockages, + negzQ: &negzQ, + zbucket_reach: &zbucket_reach, + negzQ_reach: &negzQ_reach, + d: &d, + eid_client: &eid_client, + ebucket: &ebucket, + elevel: &elevel, + esince: &esince, + einvremain: &einvremain, + eblockages: &eblockages, + id_client: &id_client, + inv_id_client: &inv_id_client, + einv_id_client: &einv_id_client, + invremain_inverse: &invremain_inverse, + zinvremain_inverse: &zinvremain_inverse, + }, + ) + .0; + + Ok(( + Request { + P, + id: lox_cred.id, + CBucket, + CLevel, + CSince, + CInvRemain, + CBlockages, + CQ, + P_reach, + CBucket_reach, + CQ_reach, + D, + EncIdClient, + EncBucket, + EncLevel, + EncSince, + EncInvRemain, + EncBlockages, + EncInvIdClient, + piUser, + }, + State { + d, + D, + EncIdClient, + EncBucket, + EncLevel, + EncSince, + EncInvRemain, + EncBlockages, + EncInvIdClient, + id_client, + bucket: lox_cred.bucket, + level: lox_cred.trust_level, + since: lox_cred.level_since, + invremain: new_invites_remaining, + blockages: lox_cred.blockages, + inv_id_client, + }, + )) +} diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs index 9eafe96..7a1c1bf 100644 --- a/crates/lox-library/src/proto/level_up.rs +++ b/crates/lox-library/src/proto/level_up.rs @@ -76,6 +76,8 @@ pub const LEVEL_INVITATIONS: [u32; MAX_LEVEL + 1] = [0, 2, 4, 6, 8]; /// blockages this credential is allowed to have recorded in order to /// advance from level i to level i+1. Again the LEVEL_INVITATIONS\[0\] /// entry is a dummy, as for LEVEL_INTERVAL. +// If you change this to have a number greater than 7, you need to add +// one or more bits to the ZKP. pub const MAX_BLOCKAGES: [u32; MAX_LEVEL + 1] = [0, 4, 3, 2, 2]; pub struct Request { @@ -399,7 +401,7 @@ pub fn request( // Encrypt the other blinded fields (times B) to D as well let ebucket = Scalar::random(&mut rng); let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D); - let newinvites: Scalar = LEVEL_INVITATIONS[new_level as usize].into(); + let newinvites: Scalar = LEVEL_INVITATIONS[trust_level as usize].into(); let eblockages = Scalar::random(&mut rng); let EncBlockages = ( &eblockages * Btable, @@ -830,7 +832,7 @@ impl BridgeAuth { // Create the invitations_remaining attribute (Scalar), which is // the number of invitations at the new level - let invitations_remaining: Scalar = LEVEL_INVITATIONS[new_level].into(); + let invitations_remaining: Scalar = LEVEL_INVITATIONS[level].into(); // Compute the MAC on the visible attributes let b = Scalar::random(&mut rng); diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index d8ef0fc..38d23cc 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -200,3 +200,35 @@ fn test_level_up() { println!("cred4 = {:?}", cred4); assert!(ba.verify_lox(&cred4)); } + +#[test] +fn test_issue_inv() { + let (bdb, mut ba) = setup(); + let cred1 = level0_migration(&bdb, &mut ba); + assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); + + // Time passes + ba.advance_days(20); + + let cred2 = level_up(&mut ba, &cred1); + assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); + println!("cred2 = {:?}", cred2); + assert!(ba.verify_lox(&cred2)); + + // Read the bucket in the credential to get today's Bucket + // Reachability credential + let (id, key) = bridge_table::from_scalar(cred2.bucket).unwrap(); + let encbuckets = ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); + let reachcred = bucket.1.unwrap(); + + let (req, state) = issue_invite::request( + &cred2, + &reachcred, + &ba.lox_pub, + &ba.reachability_pub, + ba.today(), + ) + .unwrap(); +} From a6d98dde735b301b90c06f34b23d06f5f0630a3c Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Tue, 4 May 2021 12:02:43 -0400 Subject: [PATCH 038/115] The response message of the issue invitation protocol --- crates/lox-library/src/proto/issue_invite.rs | 358 ++++++++++++++++++- crates/lox-library/src/proto/level_up.rs | 5 +- crates/lox-library/src/tests.rs | 1 + 3 files changed, 357 insertions(+), 7 deletions(-) diff --git a/crates/lox-library/src/proto/issue_invite.rs b/crates/lox-library/src/proto/issue_invite.rs index bee4bc9..faee7e4 100644 --- a/crates/lox-library/src/proto/issue_invite.rs +++ b/crates/lox-library/src/proto/issue_invite.rs @@ -56,7 +56,7 @@ use zkp::Transcript; use super::super::cred; use super::super::dup_filter::SeenType; -use super::super::{pt_dbl, scalar_dbl, scalar_u32}; +use super::super::scalar_u32; use super::super::{BridgeAuth, IssuerPubKey}; use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; @@ -129,8 +129,15 @@ pub struct Response { TSince: RistrettoPoint, TInvRemain: RistrettoPoint, TBlockages: RistrettoPoint, + + // The fields for the new Invitation credential + P_inv: RistrettoPoint, + EncQ_inv: (RistrettoPoint, RistrettoPoint), inv_id_server: Scalar, - TInvId: RistrettoPoint, + TId_inv: RistrettoPoint, + date_inv: Scalar, + TBucket_inv: RistrettoPoint, + TBlockages_inv: RistrettoPoint, // The ZKP piBlindIssue: CompactProof, @@ -183,6 +190,67 @@ define_proof! { EncInvIdClient1 = (inv_id_client*B + einv_id_client*D) } +define_proof! { + blindissue, + "Issue Invite Issuing", + (x0, x0tilde, xid, xbucket, xlevel, xsince, xinvremain, xblockages, + s, b, tid, tbucket, tlevel, tsince, tinvremain, tblockages, + x0_inv, x0tilde_inv, xid_inv, xdate_inv, xbucket_inv, + xblockages_inv, + s_inv, b_inv, tid_inv, tbucket_inv, tblockages_inv), + (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xlevel, Xsince, Xinvremain, + Xblockages, TId, TBucket, TLevel, TSince, TInvRemain, TBlockages, + P_inv, EncQ_inv0, EncQ_inv1, X0_inv, Xid_inv, Xdate_inv, + Xbucket_inv, Xblockages_inv, Pdate_inv, TId_inv, TBucket_inv, + TBlockages_inv, + D, EncId0, EncId1, EncBucket0, EncBucket1, EncLevel0, EncLevel1, + EncSince0, EncSince1, EncInvRemain0, EncInvRemain1, + EncBlockages0, EncBlockages1, + EncInvId0, EncInvId1), + (A, B): + Xid = (xid*A), + Xbucket = (xbucket*A), + Xlevel = (xlevel*A), + Xsince = (xsince*A), + Xinvremain = (xinvremain*A), + Xblockages = (xblockages*A), + X0 = (x0*B + x0tilde*A), + P = (b*B), + TId = (b*Xid), + TId = (tid*A), + TBucket = (b*Xbucket), + TBucket = (tbucket*A), + TLevel = (b*Xlevel), + TLevel = (tlevel*A), + TSince = (b*Xsince), + TSince = (tsince*A), + TInvRemain = (b*Xinvremain), + TInvRemain = (tinvremain*A), + TBlockages = (b*Xblockages), + TBlockages = (tblockages*A), + EncQ0 = (s*B + tid*EncId0 + tbucket*EncBucket0 + tlevel*EncLevel0 + + tsince*EncSince0 + tinvremain*EncInvRemain0 + tblockages*EncBlockages0), + EncQ1 = (s*D + tid*EncId1 + tbucket*EncBucket1 + tlevel*EncLevel1 + + tsince*EncSince1 + tinvremain*EncInvRemain1 + tblockages*EncBlockages1 + + x0*P), + Xid_inv = (xid_inv*A), + Xdate_inv = (xdate_inv*A), + Xbucket_inv = (xbucket_inv*A), + Xblockages_inv = (xblockages_inv*A), + X0_inv = (x0_inv*B + x0tilde_inv*A), + P_inv = (b_inv*B), + TId_inv = (b_inv*Xid_inv), + TId_inv = (tid_inv*A), + TBucket_inv = (b_inv*Xbucket_inv), + TBucket_inv = (tbucket_inv*A), + TBlockages_inv = (b_inv*Xblockages_inv), + TBlockages_inv = (tblockages_inv*A), + EncQ_inv0 = (s_inv*B + tid_inv*EncInvId0 + tbucket_inv*EncBucket0 + + tblockages_inv*EncBlockages0), + EncQ_inv1 = (s_inv*D + tid_inv*EncInvId1 + tbucket_inv*EncBucket1 + + tblockages_inv*EncBlockages1 + x0_inv*P_inv + xdate_inv*Pdate_inv) +} + pub fn request( lox_cred: &cred::Lox, reach_cred: &cred::BucketReachability, @@ -231,7 +299,7 @@ pub fn request( let zinvremain = Scalar::random(&mut rng); let zblockages = Scalar::random(&mut rng); let CBucket = lox_cred.bucket * P + &zbucket * Atable; - let CLevel = lox_cred.bucket * P + &zlevel * Atable; + let CLevel = lox_cred.trust_level * P + &zlevel * Atable; let CSince = lox_cred.level_since * P + &zsince * Atable; let CInvRemain = lox_cred.invites_remaining * P + &zinvremain * Atable; let CBlockages = lox_cred.blockages * P + &zblockages * Atable; @@ -320,7 +388,7 @@ pub fn request( let einv_id_client = Scalar::random(&mut rng); let EncInvIdClient = ( &einv_id_client * Btable, - &id_client * Btable + einv_id_client * D, + &inv_id_client * Btable + einv_id_client * D, ); // The proof that invites_remaining is not zero. We prove this by @@ -441,3 +509,285 @@ pub fn request( }, )) } + +impl BridgeAuth { + /// Receive an issue invite request + pub fn handle_issue_invite(&mut self, req: Request) -> Result { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + if req.P.is_identity() || req.P_reach.is_identity() { + return Err(ProofError::VerificationFailure); + } + + let today: Scalar = self.today().into(); + + // Recompute the "error factors" using knowledge of our own + // (the issuer's) private key instead of knowledge of the + // hidden attributes + let Vprime = (self.lox_priv.x[0] + self.lox_priv.x[1] * req.id) * req.P + + self.lox_priv.x[2] * req.CBucket + + self.lox_priv.x[3] * req.CLevel + + self.lox_priv.x[4] * req.CSince + + self.lox_priv.x[5] * req.CInvRemain + + self.lox_priv.x[6] * req.CBlockages + - req.CQ; + + let Vprime_reach = (self.reachability_priv.x[0] + self.reachability_priv.x[1] * today) + * req.P_reach + + self.reachability_priv.x[2] * req.CBucket_reach + - req.CQ_reach; + + // Verify the ZKP + let mut transcript = Transcript::new(b"issue invite request"); + requestproof::verify_compact( + &req.piUser, + &mut transcript, + requestproof::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P: &req.P.compress(), + CBucket: &req.CBucket.compress(), + CLevel: &req.CLevel.compress(), + CSince: &req.CSince.compress(), + CInvRemain: &req.CInvRemain.compress(), + CBlockages: &req.CBlockages.compress(), + V: &Vprime.compress(), + Xbucket: &self.lox_pub.X[2].compress(), + Xlevel: &self.lox_pub.X[3].compress(), + Xsince: &self.lox_pub.X[4].compress(), + Xinvremain: &self.lox_pub.X[5].compress(), + Xblockages: &self.lox_pub.X[6].compress(), + P_reach: &req.P_reach.compress(), + CBucket_reach: &req.CBucket_reach.compress(), + V_reach: &Vprime_reach.compress(), + Xbucket_reach: &self.reachability_pub.X[2].compress(), + D: &req.D.compress(), + EncIdClient0: &req.EncIdClient.0.compress(), + EncIdClient1: &req.EncIdClient.1.compress(), + EncBucket0: &req.EncBucket.0.compress(), + EncBucket1: &req.EncBucket.1.compress(), + EncLevel0: &req.EncLevel.0.compress(), + EncLevel1: &req.EncLevel.1.compress(), + EncSince0: &req.EncSince.0.compress(), + EncSince1: &req.EncSince.1.compress(), + EncInvRemain0: &req.EncInvRemain.0.compress(), + EncInvRemain1_plus_B: &(req.EncInvRemain.1 + B).compress(), + EncBlockages0: &req.EncBlockages.0.compress(), + EncBlockages1: &req.EncBlockages.1.compress(), + EncInvIdClient0: &req.EncInvIdClient.0.compress(), + EncInvIdClient1: &req.EncInvIdClient.1.compress(), + }, + )?; + + // Ensure the id has not been seen before, and add it to the + // seen list. + if self.id_filter.filter(&req.id) == SeenType::Seen { + return Err(ProofError::VerificationFailure); + } + + // Blind issuing of the new Lox credential + + // Choose a random server id component to add to the client's + // (blinded) id component + let mut rng = rand::thread_rng(); + let id_server = Scalar::random(&mut rng); + let EncId = (req.EncIdClient.0, req.EncIdClient.1 + &id_server * Btable); + + // Compute the MAC on the visible attributes (none here) + let b = Scalar::random(&mut rng); + let P = &b * Btable; + let QHc = self.lox_priv.x[0] * P; + + // El Gamal encrypt it to the public key req.D + let s = Scalar::random(&mut rng); + let EncQHc = (&s * Btable, QHc + s * req.D); + + // Homomorphically compute the part of the MAC corresponding to + // the blinded attributes + let tid = self.lox_priv.x[1] * b; + let TId = &tid * Atable; + let EncQId = (tid * EncId.0, tid * EncId.1); + let tbucket = self.lox_priv.x[2] * b; + let TBucket = &tbucket * Atable; + let EncQBucket = (tbucket * req.EncBucket.0, tbucket * req.EncBucket.1); + let tlevel = self.lox_priv.x[3] * b; + let TLevel = &tlevel * Atable; + let EncQLevel = (tlevel * req.EncLevel.0, tlevel * req.EncLevel.1); + let tsince = self.lox_priv.x[4] * b; + let TSince = &tsince * Atable; + let EncQSince = (tsince * req.EncSince.0, tsince * req.EncSince.1); + let tinvremain = self.lox_priv.x[5] * b; + let TInvRemain = &tinvremain * Atable; + let EncQInvRemain = ( + tinvremain * req.EncInvRemain.0, + tinvremain * req.EncInvRemain.1, + ); + let tblockages = self.lox_priv.x[6] * b; + let TBlockages = &tblockages * Atable; + let EncQBlockages = ( + tblockages * req.EncBlockages.0, + tblockages * req.EncBlockages.1, + ); + + let EncQ = ( + EncQHc.0 + + EncQId.0 + + EncQBucket.0 + + EncQLevel.0 + + EncQSince.0 + + EncQInvRemain.0 + + EncQBlockages.0, + EncQHc.1 + + EncQId.1 + + EncQBucket.1 + + EncQLevel.1 + + EncQSince.1 + + EncQInvRemain.1 + + EncQBlockages.1, + ); + + // Blind issuing of the new Invitation credential + + // Choose a random server id component to add to the client's + // (blinded) id component + let inv_id_server = Scalar::random(&mut rng); + let EncInvId = ( + req.EncInvIdClient.0, + req.EncInvIdClient.1 + &inv_id_server * Btable, + ); + + // Compute the MAC on the visible attributes + let b_inv = Scalar::random(&mut rng); + let P_inv = &b_inv * Btable; + let QHc_inv = (self.invitation_priv.x[0] + self.invitation_priv.x[2] * today) * P; + + // El Gamal encrypt it to the public key req.D + let s_inv = Scalar::random(&mut rng); + let EncQHc_inv = (&s_inv * Btable, QHc_inv + s_inv * req.D); + + // Homomorphically compute the part of the MAC corresponding to + // the blinded attributes + let tinvid = self.invitation_priv.x[1] * b_inv; + let TId_inv = &tinvid * Atable; + let EncQInvId = (tinvid * EncInvId.0, tinvid * EncInvId.1); + let tinvbucket = self.invitation_priv.x[3] * b_inv; + let TBucket_inv = &tinvbucket * Atable; + // The bucket and blockages encrypted attributes are reused from + // the Lox credential + let EncQInvBucket = (tinvbucket * req.EncBucket.0, tinvbucket * req.EncBucket.1); + let tinvblockages = self.invitation_priv.x[4] * b_inv; + let TBlockages_inv = &tinvblockages * Atable; + let EncQInvBlockages = ( + tinvblockages * req.EncBlockages.0, + tinvblockages * req.EncBlockages.1, + ); + + let EncQ_inv = ( + EncQHc_inv.0 + EncQInvId.0 + EncQInvBucket.0 + EncQInvBlockages.0, + EncQHc_inv.1 + EncQInvId.1 + EncQInvBucket.1 + EncQInvBlockages.1, + ); + + let mut transcript = Transcript::new(b"issue invite issuing"); + let piBlindIssue = blindissue::prove_compact( + &mut transcript, + blindissue::ProveAssignments { + A: &A, + B: &B, + P: &P, + EncQ0: &EncQ.0, + EncQ1: &EncQ.1, + X0: &self.lox_pub.X[0], + Xid: &self.lox_pub.X[1], + Xbucket: &self.lox_pub.X[2], + Xlevel: &self.lox_pub.X[3], + Xsince: &self.lox_pub.X[4], + Xinvremain: &self.lox_pub.X[5], + Xblockages: &self.lox_pub.X[6], + TId: &TId, + TBucket: &TBucket, + TLevel: &TLevel, + TSince: &TSince, + TInvRemain: &TInvRemain, + TBlockages: &TBlockages, + P_inv: &P_inv, + EncQ_inv0: &EncQ_inv.0, + EncQ_inv1: &EncQ_inv.1, + X0_inv: &self.invitation_pub.X[0], + Xid_inv: &self.invitation_pub.X[1], + Xdate_inv: &self.invitation_pub.X[2], + Xbucket_inv: &self.invitation_pub.X[3], + Xblockages_inv: &self.invitation_pub.X[4], + Pdate_inv: &(today * P_inv), + TId_inv: &TId_inv, + TBucket_inv: &TBucket_inv, + TBlockages_inv: &TBlockages_inv, + D: &req.D, + EncId0: &EncId.0, + EncId1: &EncId.1, + EncBucket0: &req.EncBucket.0, + EncBucket1: &req.EncBucket.1, + EncLevel0: &req.EncLevel.0, + EncLevel1: &req.EncLevel.1, + EncSince0: &req.EncSince.0, + EncSince1: &req.EncSince.1, + EncInvRemain0: &req.EncInvRemain.0, + EncInvRemain1: &req.EncInvRemain.1, + EncBlockages0: &req.EncBlockages.0, + EncBlockages1: &req.EncBlockages.1, + EncInvId0: &EncInvId.0, + EncInvId1: &EncInvId.1, + x0: &self.lox_priv.x[0], + x0tilde: &self.lox_priv.x0tilde, + xid: &self.lox_priv.x[1], + xbucket: &self.lox_priv.x[2], + xlevel: &self.lox_priv.x[3], + xsince: &self.lox_priv.x[4], + xinvremain: &self.lox_priv.x[5], + xblockages: &self.lox_priv.x[6], + s: &s, + b: &b, + tid: &tid, + tbucket: &tbucket, + tlevel: &tlevel, + tsince: &tsince, + tinvremain: &tinvremain, + tblockages: &tblockages, + x0_inv: &self.invitation_priv.x[0], + x0tilde_inv: &self.invitation_priv.x0tilde, + xid_inv: &self.invitation_priv.x[1], + xdate_inv: &self.invitation_priv.x[2], + xbucket_inv: &self.invitation_priv.x[3], + xblockages_inv: &self.invitation_priv.x[4], + s_inv: &s_inv, + b_inv: &b_inv, + tid_inv: &tinvid, + tbucket_inv: &tinvbucket, + tblockages_inv: &tinvblockages, + }, + ) + .0; + + Ok(Response { + P, + EncQ, + id_server, + TId, + TBucket, + TLevel, + TSince, + TInvRemain, + TBlockages, + P_inv, + EncQ_inv, + inv_id_server, + TId_inv, + date_inv: today, + TBucket_inv, + TBlockages_inv, + piBlindIssue, + }) + } +} diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs index 7a1c1bf..ee64b80 100644 --- a/crates/lox-library/src/proto/level_up.rs +++ b/crates/lox-library/src/proto/level_up.rs @@ -243,9 +243,8 @@ define_proof! { D, EncId0, EncId1, EncBucket0, EncBucket1, EncBlockages0, EncBlockages1), (A, B): Xid = (xid*A), - Xid = (xid*A), - Xlevel = (xlevel*A), Xbucket = (xbucket*A), + Xlevel = (xlevel*A), Xsince = (xsince*A), Xinvremain = (xinvremain*A), Xblockages = (xblockages*A), @@ -700,7 +699,7 @@ impl BridgeAuth { let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; - if req.P.is_identity() { + if req.P.is_identity() || req.P_reach.is_identity() { return Err(ProofError::VerificationFailure); } diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 38d23cc..6bd1b79 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -231,4 +231,5 @@ fn test_issue_inv() { ba.today(), ) .unwrap(); + let resp = ba.handle_issue_invite(req).unwrap(); } From 8b517aa4c8885f01a17461c16347794f2d87dde9 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Tue, 4 May 2021 14:21:38 -0400 Subject: [PATCH 039/115] Complete the issue invitation protocol --- crates/lox-library/Cargo.toml | 4 +- crates/lox-library/src/proto/issue_invite.rs | 115 ++++++++++++++++++- crates/lox-library/src/tests.rs | 6 + 3 files changed, 121 insertions(+), 4 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index ea88540..0a53f27 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -7,8 +7,8 @@ edition = "2018" [dependencies] curve25519-dalek = { package = "curve25519-dalek-ng", version = "3", default-features = false, features = ["serde", "std"] } ed25519-dalek = "1" -# zkp = { version = "0.8", features = ["debug-transcript"] } -zkp = "0.8" +zkp = { version = "0.8", features = ["debug-transcript"] } +# zkp = "0.8" bincode = "1" rand = "0.7" serde = "1" diff --git a/crates/lox-library/src/proto/issue_invite.rs b/crates/lox-library/src/proto/issue_invite.rs index faee7e4..699b660 100644 --- a/crates/lox-library/src/proto/issue_invite.rs +++ b/crates/lox-library/src/proto/issue_invite.rs @@ -282,7 +282,7 @@ pub fn request( return Err(ProofError::VerificationFailure); } // The new invites_remaining - let new_invites_remaining = &lox_cred.invites_remaining - Scalar::one(); + let new_invites_remaining = lox_cred.invites_remaining - Scalar::one(); // Blind showing the Lox credential @@ -662,7 +662,7 @@ impl BridgeAuth { // Compute the MAC on the visible attributes let b_inv = Scalar::random(&mut rng); let P_inv = &b_inv * Btable; - let QHc_inv = (self.invitation_priv.x[0] + self.invitation_priv.x[2] * today) * P; + let QHc_inv = (self.invitation_priv.x[0] + self.invitation_priv.x[2] * today) * P_inv; // El Gamal encrypt it to the public key req.D let s_inv = Scalar::random(&mut rng); @@ -791,3 +791,114 @@ impl BridgeAuth { }) } } + +/// Handle the response to the request, producing the new Lox credential +/// and Invitation credential if successful. +pub fn handle_response( + state: State, + resp: Response, + lox_pub: &IssuerPubKey, + invitation_pub: &IssuerPubKey, +) -> Result<(cred::Lox, cred::Invitation), ProofError> { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + if resp.P.is_identity() || resp.P_inv.is_identity() { + return Err(ProofError::VerificationFailure); + } + + // Add the server's contribution to the id to our own, both in plain + // and encrypted form and for both the Lox credential id and the + // Invitation credential id + let id = state.id_client + resp.id_server; + let EncId = ( + state.EncIdClient.0, + state.EncIdClient.1 + &resp.id_server * Btable, + ); + + let inv_id = state.inv_id_client + resp.inv_id_server; + let EncInvId = ( + state.EncInvIdClient.0, + state.EncInvIdClient.1 + &resp.inv_id_server * Btable, + ); + + // Verify the proof + let mut transcript = Transcript::new(b"issue invite issuing"); + blindissue::verify_compact( + &resp.piBlindIssue, + &mut transcript, + blindissue::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P: &resp.P.compress(), + EncQ0: &resp.EncQ.0.compress(), + EncQ1: &resp.EncQ.1.compress(), + X0: &lox_pub.X[0].compress(), + Xid: &lox_pub.X[1].compress(), + Xbucket: &lox_pub.X[2].compress(), + Xlevel: &lox_pub.X[3].compress(), + Xsince: &lox_pub.X[4].compress(), + Xinvremain: &lox_pub.X[5].compress(), + Xblockages: &lox_pub.X[6].compress(), + TId: &resp.TId.compress(), + TBucket: &resp.TBucket.compress(), + TLevel: &resp.TLevel.compress(), + TSince: &resp.TSince.compress(), + TInvRemain: &resp.TInvRemain.compress(), + TBlockages: &resp.TBlockages.compress(), + P_inv: &resp.P_inv.compress(), + EncQ_inv0: &resp.EncQ_inv.0.compress(), + EncQ_inv1: &resp.EncQ_inv.1.compress(), + X0_inv: &invitation_pub.X[0].compress(), + Xid_inv: &invitation_pub.X[1].compress(), + Xdate_inv: &invitation_pub.X[2].compress(), + Xbucket_inv: &invitation_pub.X[3].compress(), + Xblockages_inv: &invitation_pub.X[4].compress(), + Pdate_inv: &(resp.date_inv * resp.P_inv).compress(), + TId_inv: &resp.TId_inv.compress(), + TBucket_inv: &resp.TBucket_inv.compress(), + TBlockages_inv: &resp.TBlockages_inv.compress(), + D: &state.D.compress(), + EncId0: &EncId.0.compress(), + EncId1: &EncId.1.compress(), + EncBucket0: &state.EncBucket.0.compress(), + EncBucket1: &state.EncBucket.1.compress(), + EncLevel0: &state.EncLevel.0.compress(), + EncLevel1: &state.EncLevel.1.compress(), + EncSince0: &state.EncSince.0.compress(), + EncSince1: &state.EncSince.1.compress(), + EncInvRemain0: &state.EncInvRemain.0.compress(), + EncInvRemain1: &state.EncInvRemain.1.compress(), + EncBlockages0: &state.EncBlockages.0.compress(), + EncBlockages1: &state.EncBlockages.1.compress(), + EncInvId0: &EncInvId.0.compress(), + EncInvId1: &EncInvId.1.compress(), + }, + )?; + + // Decrypt EncQ and EncQ_inv + let Q = resp.EncQ.1 - (state.d * resp.EncQ.0); + let Q_inv = resp.EncQ_inv.1 - (state.d * resp.EncQ_inv.0); + + Ok(( + cred::Lox { + P: resp.P, + Q, + id, + bucket: state.bucket, + trust_level: state.level, + level_since: state.since, + invites_remaining: state.invremain, + blockages: state.blockages, + }, + cred::Invitation { + P: resp.P_inv, + Q: Q_inv, + inv_id, + date: resp.date_inv, + bucket: state.bucket, + blockages: state.blockages, + }, + )) +} diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 6bd1b79..183ec2d 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -232,4 +232,10 @@ fn test_issue_inv() { ) .unwrap(); let resp = ba.handle_issue_invite(req).unwrap(); + let (cred3, invite) = + issue_invite::handle_response(state, resp, &ba.lox_pub, &ba.invitation_pub).unwrap(); + assert!(ba.verify_lox(&cred3)); + assert!(ba.verify_invitation(&invite)); + println!("cred3 = {:?}", cred3); + println!("invite = {:?}", invite); } From dd505ccfd7af56deaa1e9aa4fc72f4056d8130cc Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Tue, 4 May 2021 15:47:37 -0400 Subject: [PATCH 040/115] The request message of the redeem invitation protocol --- crates/lox-library/src/lib.rs | 1 + crates/lox-library/src/proto/redeem_invite.rs | 350 ++++++++++++++++++ crates/lox-library/src/tests.rs | 71 +++- 3 files changed, 402 insertions(+), 20 deletions(-) create mode 100644 crates/lox-library/src/proto/redeem_invite.rs diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 2fbf9b0..f6c3de4 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -401,6 +401,7 @@ pub mod proto { pub mod level_up; pub mod migration; pub mod open_invite; + pub mod redeem_invite; pub mod trust_promotion; } diff --git a/crates/lox-library/src/proto/redeem_invite.rs b/crates/lox-library/src/proto/redeem_invite.rs new file mode 100644 index 0000000..a5373d6 --- /dev/null +++ b/crates/lox-library/src/proto/redeem_invite.rs @@ -0,0 +1,350 @@ +/*! A module for the protocol for a new user to redeem an Invitation +credential. The user will start at trust level 1 (instead of 0 for +untrusted uninvited users). + +The user presents the Invitation credential: +- id: revealed +- date: blinded, but proved in ZK to be at most INVITATION_EXPIRY days ago +- bucket: blinded +- blockages: blinded + +and a new Lox credential to be issued: + +- id: jointly chosen by the user and BA +- bucket: blinded, but proved in ZK that it's the same as in the + Invitation credential above +- trust_level: revealed to be 1 +- level_since: today +- invites_remaining: revealed to be 0 +- blockages: blinded, but proved in ZK that it's the same as in the + Invitations credential above + +*/ + +use curve25519_dalek::ristretto::RistrettoBasepointTable; +use curve25519_dalek::ristretto::RistrettoPoint; +use curve25519_dalek::scalar::Scalar; +use curve25519_dalek::traits::IsIdentity; + +use zkp::CompactProof; +use zkp::ProofError; +use zkp::Transcript; + +use super::super::cred; +use super::super::dup_filter::SeenType; +use super::super::{pt_dbl, scalar_dbl, scalar_u32}; +use super::super::{BridgeAuth, IssuerPubKey}; +use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; + +/// Invitations must be used within this many days of being issued. +/// Note that if you change this number to be larger than 15, you must +/// also add bits to the zero knowledge proof. +pub const INVITATION_EXPIRY: u32 = 15; + +pub struct Request { + // Fields for showing the Invitation credential + P: RistrettoPoint, + id: Scalar, + CDate: RistrettoPoint, + CBucket: RistrettoPoint, + CBlockages: RistrettoPoint, + CQ: RistrettoPoint, + + // Fields for the inequality proof + // date + INVITATION_EXPIRY >= today + CG1: RistrettoPoint, + CG2: RistrettoPoint, + CG3: RistrettoPoint, + CG0sq: RistrettoPoint, + CG1sq: RistrettoPoint, + CG2sq: RistrettoPoint, + CG3sq: RistrettoPoint, + + // Fields for user blinding of the Lox credential to be issued + D: RistrettoPoint, + EncIdClient: (RistrettoPoint, RistrettoPoint), + EncBucket: (RistrettoPoint, RistrettoPoint), + EncBlockages: (RistrettoPoint, RistrettoPoint), + + // The combined ZKP + piUser: CompactProof, +} + +#[derive(Debug)] +pub struct State { + d: Scalar, + D: RistrettoPoint, + EncIdClient: (RistrettoPoint, RistrettoPoint), + EncBucket: (RistrettoPoint, RistrettoPoint), + EncBlockages: (RistrettoPoint, RistrettoPoint), + id_client: Scalar, + bucket: Scalar, + blockages: Scalar, +} + +pub struct Response { + // The fields for the new Lox credential; the new trust level is 1 + // and the new invites_remaining is 0, so we don't have to include + // them here explicitly + P: RistrettoPoint, + EncQ: (RistrettoPoint, RistrettoPoint), + id_server: Scalar, + level_since: Scalar, + TId: RistrettoPoint, + TBucket: RistrettoPoint, + TBlockages: RistrettoPoint, + + // The ZKP + piBlindIssue: CompactProof, +} + +define_proof! { + requestproof, + "Redeem Invite Request", + (date, bucket, blockages, zdate, zbucket, zblockages, negzQ, + d, eid_client, ebucket, eblockages, id_client, + g0, g1, g2, g3, + zg0, zg1, zg2, zg3, + wg0, wg1, wg2, wg3, + yg0, yg1, yg2, yg3), + (P, CDate, CBucket, CBlockages, V, Xdate, Xbucket, Xblockages, + D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1, + EncBlockages0, EncBlockages1, + CG0, CG1, CG2, CG3, + CG0sq, CG1sq, CG2sq, CG3sq), + (A, B): + // Blind showing of the Invitation credential + CDate = (date*P + zdate*A), + CBucket = (bucket*P + zbucket*A), + CBlockages = (blockages*P + zblockages*A), + // User blinding of the Lox credential to be issued + D = (d*B), + EncIdClient0 = (eid_client*B), + EncIdClient1 = (id_client*B + eid_client*D), + EncBucket0 = (ebucket*B), + EncBucket1 = (bucket*B + ebucket*D), + EncBlockages0 = (eblockages*B), + EncBlockages1 = (blockages*B + eblockages*D), + // Prove CDate encodes a value at most INVITATION_EXPIRY + // days ago: first prove each of g0, ..., g3 is a bit by + // proving that gi = gi^2 + CG0 = (g0*P + zg0*A), CG0sq = (g0*CG0 + wg0*A), CG0sq = (g0*P + yg0*A), + CG1 = (g1*P + zg1*A), CG1sq = (g1*CG1 + wg1*A), CG1sq = (g1*P + yg1*A), + CG2 = (g2*P + zg2*A), CG2sq = (g2*CG2 + wg2*A), CG2sq = (g2*P + yg2*A), + CG3 = (g3*P + zg3*A), CG3sq = (g3*CG3 + wg3*A), CG3sq = (g3*P + yg3*A) + // Then we'll check that today*P + CG0 + 2*CG1 + 4*CG2 + 8*CG3 = + // CDate + INVITATION_EXPIRY*P by having the verifier + // plug in CDate + INVITATION_EXPIRY*P - (today*P + 2*CG1 + 4*CG2 + // + 8*CG3) as its value of CG0. +} + +pub fn request( + inv_cred: &cred::Invitation, + invitation_pub: &IssuerPubKey, + today: u32, +) -> Result<(Request, State), ProofError> { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + // Ensure the credential can be correctly shown: it must be the case + // that date + INVITATION_EXPIRY >= today. + let date: u32 = match scalar_u32(&inv_cred.date) { + Some(v) => v, + None => return Err(ProofError::VerificationFailure), + }; + if date + INVITATION_EXPIRY < today { + return Err(ProofError::VerificationFailure); + } + let diffdays = date + INVITATION_EXPIRY - today; + // If diffdays > 15, then since INVITATION_EXPIRY <= 15, then date + // must be in the future. Reject. + if diffdays > 15 { + return Err(ProofError::VerificationFailure); + } + + // Blind showing the Invitation credential + + // Reblind P and Q + let mut rng = rand::thread_rng(); + let t = Scalar::random(&mut rng); + let P = t * inv_cred.P; + let Q = t * inv_cred.Q; + + // Form Pedersen commitments to the blinded attributes + let zdate = Scalar::random(&mut rng); + let zbucket = Scalar::random(&mut rng); + let zblockages = Scalar::random(&mut rng); + let CDate = inv_cred.date * P + &zdate * Atable; + let CBucket = inv_cred.bucket * P + &zbucket * Atable; + let CBlockages = inv_cred.blockages * P + &zblockages * Atable; + + // Form a Pedersen commitment to the MAC Q + // We flip the sign of zQ from that of the Hyphae paper so that + // the ZKP has a "+" instead of a "-", as that's what the zkp + // macro supports. + let negzQ = Scalar::random(&mut rng); + let CQ = Q - &negzQ * Atable; + + // Compute the "error factor" + let V = zdate * invitation_pub.X[2] + + zbucket * invitation_pub.X[3] + + zblockages * invitation_pub.X[4] + + &negzQ * Atable; + + // User blinding for the Lox certificate to be issued + + // Pick an ElGamal keypair + let d = Scalar::random(&mut rng); + let D = &d * Btable; + + // Pick a random client component of the id + let id_client = Scalar::random(&mut rng); + + // Encrypt it (times the basepoint B) to the ElGamal public key D we + // just created + let eid_client = Scalar::random(&mut rng); + let EncIdClient = (&eid_client * Btable, &id_client * Btable + eid_client * D); + + // Encrypt the other blinded fields (times B) to D as well + let ebucket = Scalar::random(&mut rng); + let EncBucket = (&ebucket * Btable, &inv_cred.bucket * Btable + ebucket * D); + let eblockages = Scalar::random(&mut rng); + let EncBlockages = ( + &eblockages * Btable, + &inv_cred.blockages * Btable + eblockages * D, + ); + + // The range proof that 0 <= diffdays <= 15 + + // Extract the 4 bits from diffdays + let g0: Scalar = (diffdays & 1).into(); + let g1: Scalar = ((diffdays >> 1) & 1).into(); + let g2: Scalar = ((diffdays >> 2) & 1).into(); + let g3: Scalar = ((diffdays >> 3) & 1).into(); + + // Pick random factors for the Pedersen commitments + let wg0 = Scalar::random(&mut rng); + let zg1 = Scalar::random(&mut rng); + let wg1 = Scalar::random(&mut rng); + let zg2 = Scalar::random(&mut rng); + let wg2 = Scalar::random(&mut rng); + let zg3 = Scalar::random(&mut rng); + let wg3 = Scalar::random(&mut rng); + + // Compute zg0 to cancel things out as + // zg0 = -(zdate + 2*zg1 + 4*zg2 + 8*zg3) + // but use Horner's method + let zg0 = -(scalar_dbl(&(scalar_dbl(&(scalar_dbl(&zg3) + zg2)) + zg1)) + zdate); + + let yg0 = wg0 + g0 * zg0; + let yg1 = wg1 + g1 * zg1; + let yg2 = wg2 + g2 * zg2; + let yg3 = wg3 + g3 * zg3; + + let CG0 = g0 * P + &zg0 * Atable; + let CG1 = g1 * P + &zg1 * Atable; + let CG2 = g2 * P + &zg2 * Atable; + let CG3 = g3 * P + &zg3 * Atable; + + let CG0sq = g0 * P + &yg0 * Atable; + let CG1sq = g1 * P + &yg1 * Atable; + let CG2sq = g2 * P + &yg2 * Atable; + let CG3sq = g3 * P + &yg3 * Atable; + + // Construct the proof + let mut transcript = Transcript::new(b"redeem invite request"); + let piUser = requestproof::prove_compact( + &mut transcript, + requestproof::ProveAssignments { + A: &A, + B: &B, + P: &P, + CDate: &CDate, + CBucket: &CBucket, + CBlockages: &CBlockages, + V: &V, + Xdate: &invitation_pub.X[2], + Xbucket: &invitation_pub.X[3], + Xblockages: &invitation_pub.X[4], + D: &D, + EncIdClient0: &EncIdClient.0, + EncIdClient1: &EncIdClient.1, + EncBucket0: &EncBucket.0, + EncBucket1: &EncBucket.1, + EncBlockages0: &EncBlockages.0, + EncBlockages1: &EncBlockages.1, + CG0: &CG0, + CG1: &CG1, + CG2: &CG2, + CG3: &CG3, + CG0sq: &CG0sq, + CG1sq: &CG1sq, + CG2sq: &CG2sq, + CG3sq: &CG3sq, + date: &inv_cred.date, + bucket: &inv_cred.bucket, + blockages: &inv_cred.blockages, + zdate: &zdate, + zbucket: &zbucket, + zblockages: &zblockages, + negzQ: &negzQ, + d: &d, + eid_client: &eid_client, + ebucket: &ebucket, + eblockages: &eblockages, + id_client: &id_client, + g0: &g0, + g1: &g1, + g2: &g2, + g3: &g3, + zg0: &zg0, + zg1: &zg1, + zg2: &zg2, + zg3: &zg3, + wg0: &wg0, + wg1: &wg1, + wg2: &wg2, + wg3: &wg3, + yg0: &yg0, + yg1: &yg1, + yg2: &yg2, + yg3: &yg3, + }, + ) + .0; + + Ok(( + Request { + P, + id: inv_cred.inv_id, + CDate, + CBucket, + CBlockages, + CQ, + D, + EncIdClient, + EncBucket, + EncBlockages, + CG1, + CG2, + CG3, + CG0sq, + CG1sq, + CG2sq, + CG3sq, + piUser, + }, + State { + d, + D, + EncIdClient, + EncBucket, + EncBlockages, + id_client, + bucket: inv_cred.bucket, + blockages: inv_cred.blockages, + }, + )) +} diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 183ec2d..71aaade 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -201,8 +201,29 @@ fn test_level_up() { assert!(ba.verify_lox(&cred4)); } +fn issue_invite(ba: &mut BridgeAuth, cred: &cred::Lox) -> (cred::Lox, cred::Invitation) { + // Read the bucket in the credential to get today's Bucket + // Reachability credential + let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); + let encbuckets = ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); + let reachcred = bucket.1.unwrap(); + + let (req, state) = issue_invite::request( + &cred, + &reachcred, + &ba.lox_pub, + &ba.reachability_pub, + ba.today(), + ) + .unwrap(); + let resp = ba.handle_issue_invite(req).unwrap(); + issue_invite::handle_response(state, resp, &ba.lox_pub, &ba.invitation_pub).unwrap() +} + #[test] -fn test_issue_inv() { +fn test_issue_invite() { let (bdb, mut ba) = setup(); let cred1 = level0_migration(&bdb, &mut ba); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); @@ -215,27 +236,37 @@ fn test_issue_inv() { println!("cred2 = {:?}", cred2); assert!(ba.verify_lox(&cred2)); - // Read the bucket in the credential to get today's Bucket - // Reachability credential - let (id, key) = bridge_table::from_scalar(cred2.bucket).unwrap(); - let encbuckets = ba.enc_bridge_table(); - let bucket = - bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); - let reachcred = bucket.1.unwrap(); - - let (req, state) = issue_invite::request( - &cred2, - &reachcred, - &ba.lox_pub, - &ba.reachability_pub, - ba.today(), - ) - .unwrap(); - let resp = ba.handle_issue_invite(req).unwrap(); - let (cred3, invite) = - issue_invite::handle_response(state, resp, &ba.lox_pub, &ba.invitation_pub).unwrap(); + let (cred3, invite) = issue_invite(&mut ba, &cred2); assert!(ba.verify_lox(&cred3)); assert!(ba.verify_invitation(&invite)); println!("cred3 = {:?}", cred3); println!("invite = {:?}", invite); } + +fn redeem_invite(ba: &mut BridgeAuth, inv: &cred::Invitation) -> cred::Lox { + let (req, state) = redeem_invite::request(&inv, &ba.invitation_pub, ba.today()).unwrap(); + panic!("Not finished") +} + +#[test] +fn test_redeem_invite() { + let (bdb, mut ba) = setup(); + let cred1 = level0_migration(&bdb, &mut ba); + assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); + + // Time passes + ba.advance_days(20); + + let cred2 = level_up(&mut ba, &cred1); + assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); + println!("cred2 = {:?}", cred2); + assert!(ba.verify_lox(&cred2)); + + let (cred3, invite) = issue_invite(&mut ba, &cred2); + println!("cred3 = {:?}", cred3); + println!("invite = {:?}", invite); + + let cred4 = redeem_invite(&mut ba, &invite); + assert!(ba.verify_lox(&cred4)); + println!("cred4 = {:?}", cred4); +} From b0290f5480820051c9df5330bdf80046eaa0aca1 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Tue, 4 May 2021 17:48:15 -0400 Subject: [PATCH 041/115] Complete the redeem invitation protocol --- crates/lox-library/Cargo.toml | 4 +- crates/lox-library/src/lib.rs | 5 +- crates/lox-library/src/proto/level_up.rs | 4 +- crates/lox-library/src/proto/redeem_invite.rs | 273 +++++++++++++++++- crates/lox-library/src/tests.rs | 6 +- 5 files changed, 282 insertions(+), 10 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index 0a53f27..ea88540 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -7,8 +7,8 @@ edition = "2018" [dependencies] curve25519-dalek = { package = "curve25519-dalek-ng", version = "3", default-features = false, features = ["serde", "std"] } ed25519-dalek = "1" -zkp = { version = "0.8", features = ["debug-transcript"] } -# zkp = "0.8" +# zkp = { version = "0.8", features = ["debug-transcript"] } +zkp = "0.8" bincode = "1" rand = "0.7" serde = "1" diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index f6c3de4..51961d4 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -206,8 +206,10 @@ pub struct BridgeAuth { /// Duplicate filter for open invitations openinv_filter: dup_filter::DupFilter, - /// Duplicate filter for credential ids + /// Duplicate filter for Lox credential ids id_filter: dup_filter::DupFilter, + /// Duplicate filter for Invitation credential ids + inv_id_filter: dup_filter::DupFilter, /// Duplicate filter for trust promotions (from untrusted level 0 to /// trusted level 1) trust_promotion_filter: dup_filter::DupFilter, @@ -246,6 +248,7 @@ impl BridgeAuth { migration_table: Default::default(), openinv_filter: Default::default(), id_filter: Default::default(), + inv_id_filter: Default::default(), trust_promotion_filter: Default::default(), time_offset: time::Duration::zero(), } diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs index ee64b80..553cdcf 100644 --- a/crates/lox-library/src/proto/level_up.rs +++ b/crates/lox-library/src/proto/level_up.rs @@ -729,8 +729,8 @@ impl BridgeAuth { - req.CQ_reach; // Recompute CG0 using Horner's method - let unt: Scalar = LEVEL_INTERVAL[level].into(); - let CG0prime = (today - unt) * req.P + let interval: Scalar = LEVEL_INTERVAL[level].into(); + let CG0prime = (today - interval) * req.P - req.CSince - pt_dbl( &(pt_dbl( diff --git a/crates/lox-library/src/proto/redeem_invite.rs b/crates/lox-library/src/proto/redeem_invite.rs index a5373d6..20570e3 100644 --- a/crates/lox-library/src/proto/redeem_invite.rs +++ b/crates/lox-library/src/proto/redeem_invite.rs @@ -44,7 +44,7 @@ pub const INVITATION_EXPIRY: u32 = 15; pub struct Request { // Fields for showing the Invitation credential P: RistrettoPoint, - id: Scalar, + inv_id: Scalar, CDate: RistrettoPoint, CBucket: RistrettoPoint, CBlockages: RistrettoPoint, @@ -138,6 +138,34 @@ define_proof! { // + 8*CG3) as its value of CG0. } +define_proof! { + blindissue, + "Redeem Invite Issuing", + (x0, x0tilde, xid, xbucket, xlevel, xsince, xblockages, + s, b, tid, tbucket, tblockages), + (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xlevel, Xsince, Xblockages, + Psince, TId, TBucket, TBlockages, + D, EncId0, EncId1, EncBucket0, EncBucket1, EncBlockages0, EncBlockages1), + (A, B): + Xid = (xid*A), + Xbucket = (xbucket*A), + Xlevel = (xlevel*A), + Xsince = (xsince*A), + Xblockages = (xblockages*A), + X0 = (x0*B + x0tilde*A), + P = (b*B), + TId = (b*Xid), + TId = (tid*A), + TBucket = (b*Xbucket), + TBucket = (tbucket*A), + TBlockages = (b*Xblockages), + TBlockages = (tblockages*A), + EncQ0 = (s*B + tid*EncId0 + tbucket*EncBucket0 + tblockages*EncBlockages0), + // level=1 (so Plevel = P) and invremain=0 (so the term is omitted) + EncQ1 = (s*D + tid*EncId1 + tbucket*EncBucket1 + + tblockages*EncBlockages1 + x0*P + xlevel*P + xsince*Psince) +} + pub fn request( inv_cred: &cred::Invitation, invitation_pub: &IssuerPubKey, @@ -234,9 +262,9 @@ pub fn request( let wg3 = Scalar::random(&mut rng); // Compute zg0 to cancel things out as - // zg0 = -(zdate + 2*zg1 + 4*zg2 + 8*zg3) + // zg0 = zdate - (2*zg1 + 4*zg2 + 8*zg3) // but use Horner's method - let zg0 = -(scalar_dbl(&(scalar_dbl(&(scalar_dbl(&zg3) + zg2)) + zg1)) + zdate); + let zg0 = zdate - scalar_dbl(&(scalar_dbl(&(scalar_dbl(&zg3) + zg2)) + zg1)); let yg0 = wg0 + g0 * zg0; let yg1 = wg1 + g1 * zg1; @@ -318,7 +346,7 @@ pub fn request( Ok(( Request { P, - id: inv_cred.inv_id, + inv_id: inv_cred.inv_id, CDate, CBucket, CBlockages, @@ -348,3 +376,240 @@ pub fn request( }, )) } + +impl BridgeAuth { + /// Receive a redeem invite request + pub fn handle_redeem_invite(&mut self, req: Request) -> Result { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + if req.P.is_identity() { + return Err(ProofError::VerificationFailure); + } + + let today: Scalar = self.today().into(); + + // Recompute the "error factor" using knowledge of our own + // (the issuer's) private key instead of knowledge of the + // hidden attributes + let Vprime = (self.invitation_priv.x[0] + self.invitation_priv.x[1] * req.inv_id) * req.P + + self.invitation_priv.x[2] * req.CDate + + self.invitation_priv.x[3] * req.CBucket + + self.invitation_priv.x[4] * req.CBlockages + - req.CQ; + + // Recompute CG0 using Horner's method + let expiry: Scalar = INVITATION_EXPIRY.into(); + let CG0prime = (expiry - today) * req.P + req.CDate + - pt_dbl(&(pt_dbl(&(pt_dbl(&req.CG3) + req.CG2)) + req.CG1)); + + // Verify the ZKP + let mut transcript = Transcript::new(b"redeem invite request"); + requestproof::verify_compact( + &req.piUser, + &mut transcript, + requestproof::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P: &req.P.compress(), + CDate: &req.CDate.compress(), + CBucket: &req.CBucket.compress(), + CBlockages: &req.CBlockages.compress(), + V: &Vprime.compress(), + Xdate: &self.invitation_pub.X[2].compress(), + Xbucket: &self.invitation_pub.X[3].compress(), + Xblockages: &self.invitation_pub.X[4].compress(), + D: &req.D.compress(), + EncIdClient0: &req.EncIdClient.0.compress(), + EncIdClient1: &req.EncIdClient.1.compress(), + EncBucket0: &req.EncBucket.0.compress(), + EncBucket1: &req.EncBucket.1.compress(), + EncBlockages0: &req.EncBlockages.0.compress(), + EncBlockages1: &req.EncBlockages.1.compress(), + CG0: &CG0prime.compress(), + CG1: &req.CG1.compress(), + CG2: &req.CG2.compress(), + CG3: &req.CG3.compress(), + CG0sq: &req.CG0sq.compress(), + CG1sq: &req.CG1sq.compress(), + CG2sq: &req.CG2sq.compress(), + CG3sq: &req.CG3sq.compress(), + }, + )?; + + // Ensure the id has not been seen before, and add it to the + // invite id seen list. + if self.inv_id_filter.filter(&req.inv_id) == SeenType::Seen { + return Err(ProofError::VerificationFailure); + } + + // Blind issuing of the new Lox credential + + // Choose a random server id component to add to the client's + // (blinded) id component + let mut rng = rand::thread_rng(); + let id_server = Scalar::random(&mut rng); + let EncId = (req.EncIdClient.0, req.EncIdClient.1 + &id_server * Btable); + + // The trust level for invitees is always 1 + let level = Scalar::one(); + + // The invites remaining for invitees is always 0 (as + // appropriate for trust level 1), so we don't need to actually + // construct it + + // Compute the MAC on the visible attributes + let b = Scalar::random(&mut rng); + let P = &b * Btable; + let QHc = + (self.lox_priv.x[0] + self.lox_priv.x[3] * level + self.lox_priv.x[4] * today) * P; + + // El Gamal encrypt it to the public key req.D + let s = Scalar::random(&mut rng); + let EncQHc = (&s * Btable, QHc + s * req.D); + + // Homomorphically compute the part of the MAC corresponding to + // the blinded attributes + let tid = self.lox_priv.x[1] * b; + let TId = &tid * Atable; + let EncQId = (tid * EncId.0, tid * EncId.1); + let tbucket = self.lox_priv.x[2] * b; + let TBucket = &tbucket * Atable; + let EncQBucket = (tbucket * req.EncBucket.0, tbucket * req.EncBucket.1); + let tblockages = self.lox_priv.x[6] * b; + let TBlockages = &tblockages * Atable; + let EncQBlockages = ( + tblockages * req.EncBlockages.0, + tblockages * req.EncBlockages.1, + ); + + let EncQ = ( + EncQHc.0 + EncQId.0 + EncQBucket.0 + EncQBlockages.0, + EncQHc.1 + EncQId.1 + EncQBucket.1 + EncQBlockages.1, + ); + + let mut transcript = Transcript::new(b"redeem invite issuing"); + let piBlindIssue = blindissue::prove_compact( + &mut transcript, + blindissue::ProveAssignments { + A: &A, + B: &B, + P: &P, + EncQ0: &EncQ.0, + EncQ1: &EncQ.1, + X0: &self.lox_pub.X[0], + Xid: &self.lox_pub.X[1], + Xbucket: &self.lox_pub.X[2], + Xlevel: &self.lox_pub.X[3], + Xsince: &self.lox_pub.X[4], + Xblockages: &self.lox_pub.X[6], + Psince: &(today * P), + TId: &TId, + TBucket: &TBucket, + TBlockages: &TBlockages, + D: &req.D, + EncId0: &EncId.0, + EncId1: &EncId.1, + EncBucket0: &req.EncBucket.0, + EncBucket1: &req.EncBucket.1, + EncBlockages0: &req.EncBlockages.0, + EncBlockages1: &req.EncBlockages.1, + x0: &self.lox_priv.x[0], + x0tilde: &self.lox_priv.x0tilde, + xid: &self.lox_priv.x[1], + xbucket: &self.lox_priv.x[2], + xlevel: &self.lox_priv.x[3], + xsince: &self.lox_priv.x[4], + xblockages: &self.lox_priv.x[6], + s: &s, + b: &b, + tid: &tid, + tbucket: &tbucket, + tblockages: &tblockages, + }, + ) + .0; + + Ok(Response { + P, + EncQ, + id_server, + level_since: today, + TId, + TBucket, + TBlockages, + piBlindIssue, + }) + } +} + +/// Handle the response to the request, producing the new Lox credential +/// if successful. +pub fn handle_response( + state: State, + resp: Response, + lox_pub: &IssuerPubKey, +) -> Result { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + if resp.P.is_identity() { + return Err(ProofError::VerificationFailure); + } + + // Add the server's contribution to the id to our own, both in plain + // and encrypted form + let id = state.id_client + resp.id_server; + let EncId = ( + state.EncIdClient.0, + state.EncIdClient.1 + &resp.id_server * Btable, + ); + + // Verify the proof + let mut transcript = Transcript::new(b"redeem invite issuing"); + blindissue::verify_compact( + &resp.piBlindIssue, + &mut transcript, + blindissue::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P: &resp.P.compress(), + EncQ0: &resp.EncQ.0.compress(), + EncQ1: &resp.EncQ.1.compress(), + X0: &lox_pub.X[0].compress(), + Xid: &lox_pub.X[1].compress(), + Xbucket: &lox_pub.X[2].compress(), + Xlevel: &lox_pub.X[3].compress(), + Xsince: &lox_pub.X[4].compress(), + Xblockages: &lox_pub.X[6].compress(), + Psince: &(resp.level_since * resp.P).compress(), + TId: &resp.TId.compress(), + TBucket: &resp.TBucket.compress(), + TBlockages: &resp.TBlockages.compress(), + D: &state.D.compress(), + EncId0: &EncId.0.compress(), + EncId1: &EncId.1.compress(), + EncBucket0: &state.EncBucket.0.compress(), + EncBucket1: &state.EncBucket.1.compress(), + EncBlockages0: &state.EncBlockages.0.compress(), + EncBlockages1: &state.EncBlockages.1.compress(), + }, + )?; + + // Decrypt EncQ + let Q = resp.EncQ.1 - (state.d * resp.EncQ.0); + + Ok(cred::Lox { + P: resp.P, + Q, + id, + bucket: state.bucket, + trust_level: Scalar::one(), + level_since: resp.level_since, + invites_remaining: Scalar::zero(), + blockages: state.blockages, + }) +} diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 71aaade..1778c50 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -245,7 +245,8 @@ fn test_issue_invite() { fn redeem_invite(ba: &mut BridgeAuth, inv: &cred::Invitation) -> cred::Lox { let (req, state) = redeem_invite::request(&inv, &ba.invitation_pub, ba.today()).unwrap(); - panic!("Not finished") + let resp = ba.handle_redeem_invite(req).unwrap(); + redeem_invite::handle_response(state, resp, &ba.lox_pub).unwrap() } #[test] @@ -266,6 +267,9 @@ fn test_redeem_invite() { println!("cred3 = {:?}", cred3); println!("invite = {:?}", invite); + // Time passes + ba.advance_days(12); + let cred4 = redeem_invite(&mut ba, &invite); assert!(ba.verify_lox(&cred4)); println!("cred4 = {:?}", cred4); From cf19bf80ee1ef8d9b468c9f26f2102ec10d43b98 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Tue, 4 May 2021 18:26:58 -0400 Subject: [PATCH 042/115] Make an easier to use test harness --- crates/lox-library/src/tests.rs | 403 +++++++++++++++++--------------- 1 file changed, 216 insertions(+), 187 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 1778c50..a960fd9 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -5,272 +5,301 @@ use super::bridge_table::BridgeLine; use super::proto::*; use super::*; +struct TestHarness { + bdb: BridgeDb, + pub ba: BridgeAuth, +} + +impl TestHarness { + fn new() -> Self { + // Create a BridegDb + let bdb = BridgeDb::new(15); + // Create a BridgeAuth + let mut ba = BridgeAuth::new(bdb.pubkey); + + // Make 15 buckets with one random bridge each + for _ in 0..15 { + let bucket: [BridgeLine; 3] = + [BridgeLine::random(), Default::default(), Default::default()]; + ba.bridge_table.new_bucket(bucket); + } + // Make 5 more buckets, each containing 3 of the previously + // created bridges + for i in 0u32..5 { + let iusize = i as usize; + let bucket: [BridgeLine; 3] = [ + ba.bridge_table.buckets[3 * iusize][0], + ba.bridge_table.buckets[3 * iusize + 1][0], + ba.bridge_table.buckets[3 * iusize + 2][0], + ]; + ba.bridge_table.new_bucket(bucket); + // Add the allowed migrations to the migration table + ba.migration_table.table.insert(3 * i, 15 + i); + ba.migration_table.table.insert(3 * i + 1, 15 + i); + ba.migration_table.table.insert(3 * i + 2, 15 + i); + } + // Create the encrypted bridge table + ba.enc_bridge_table(); + + Self { bdb, ba } + } + + fn advance_days(&mut self, days: u16) { + self.ba.advance_days(days); + } + + fn open_invite(&mut self) -> cred::Lox { + // Issue an open invitation + let inv = self.bdb.invite(); + + // Use it to get a Lox credential + let (req, state) = open_invite::request(&inv); + let resp = self.ba.handle_open_invite(req).unwrap(); + open_invite::handle_response(state, resp, &self.ba.lox_pub).unwrap() + } + + fn trust_promotion(&mut self, cred: &cred::Lox) -> cred::Migration { + let (promreq, promstate) = + trust_promotion::request(&cred, &self.ba.lox_pub, self.ba.today()).unwrap(); + let promresp = self.ba.handle_trust_promotion(promreq).unwrap(); + trust_promotion::handle_response(promstate, promresp).unwrap() + } + + fn level0_migration(&mut self, loxcred: &cred::Lox, migcred: &cred::Migration) -> cred::Lox { + let (migreq, migstate) = + migration::request(loxcred, migcred, &self.ba.lox_pub, &self.ba.migration_pub).unwrap(); + let migresp = self.ba.handle_migration(migreq).unwrap(); + migration::handle_response(migstate, migresp, &self.ba.lox_pub).unwrap() + } + + fn level_up(&mut self, cred: &cred::Lox) -> cred::Lox { + // Read the bucket in the credential to get today's Bucket + // Reachability credential + let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); + let encbuckets = self.ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); + let reachcred = bucket.1.unwrap(); + + // Use the Bucket Reachability credential to advance to the next + // level + let (req, state) = level_up::request( + &cred, + &reachcred, + &self.ba.lox_pub, + &self.ba.reachability_pub, + self.ba.today(), + ) + .unwrap(); + let resp = self.ba.handle_level_up(req).unwrap(); + level_up::handle_response(state, resp, &self.ba.lox_pub).unwrap() + } + + fn issue_invite(&mut self, cred: &cred::Lox) -> (cred::Lox, cred::Invitation) { + // Read the bucket in the credential to get today's Bucket + // Reachability credential + let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); + let encbuckets = self.ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); + let reachcred = bucket.1.unwrap(); + + let (req, state) = issue_invite::request( + &cred, + &reachcred, + &self.ba.lox_pub, + &self.ba.reachability_pub, + self.ba.today(), + ) + .unwrap(); + let resp = self.ba.handle_issue_invite(req).unwrap(); + issue_invite::handle_response(state, resp, &self.ba.lox_pub, &self.ba.invitation_pub) + .unwrap() + } + + fn redeem_invite(&mut self, inv: &cred::Invitation) -> cred::Lox { + let (req, state) = + redeem_invite::request(&inv, &self.ba.invitation_pub, self.ba.today()).unwrap(); + let resp = self.ba.handle_redeem_invite(req).unwrap(); + redeem_invite::handle_response(state, resp, &self.ba.lox_pub).unwrap() + } +} + #[test] fn test_open_invite() { - // Create a BridegDb - let bdb = BridgeDb::new(20); - // Create a BridgeAuth - let mut ba = BridgeAuth::new(bdb.pubkey); + let mut th = TestHarness::new(); - // Make 20 buckets with one random bridge each - for _ in 0..20 { - let bucket: [BridgeLine; 3] = - [BridgeLine::random(), Default::default(), Default::default()]; - ba.bridge_table.new_bucket(bucket); - } - // And 20 more with three random bridges each - for _ in 0..20 { - let bucket: [BridgeLine; 3] = [ - BridgeLine::random(), - BridgeLine::random(), - BridgeLine::random(), - ]; - ba.bridge_table.new_bucket(bucket); - } - // Create the encrypted bridge table - ba.enc_bridge_table(); - - // Issue an open invitation - let inv = bdb.invite(); - - // Use it to get a Lox credential - let (req, state) = open_invite::request(&inv); - let resp = ba.handle_open_invite(req).unwrap(); - let cred = open_invite::handle_response(state, resp, &ba.lox_pub).unwrap(); + // Join an untrusted user + let cred = th.open_invite(); // Check that we can use the credential to read a bucket let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); - let encbuckets = ba.enc_bridge_table(); + let encbuckets = th.ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("cred = {:?}", cred); println!("bucket = {:?}", bucket); assert!(bucket.1.is_none()); - assert!(ba.verify_lox(&cred)); -} - -fn setup() -> (BridgeDb, BridgeAuth) { - // Create a BridegDb - let bdb = BridgeDb::new(15); - // Create a BridgeAuth - let mut ba = BridgeAuth::new(bdb.pubkey); - - // Make 15 buckets with one random bridge each - for _ in 0..15 { - let bucket: [BridgeLine; 3] = - [BridgeLine::random(), Default::default(), Default::default()]; - ba.bridge_table.new_bucket(bucket); - } - // Make 5 more buckets, each containing 3 of the previously - // created bridges - for i in 0u32..5 { - let iusize = i as usize; - let bucket: [BridgeLine; 3] = [ - ba.bridge_table.buckets[3 * iusize][0], - ba.bridge_table.buckets[3 * iusize + 1][0], - ba.bridge_table.buckets[3 * iusize + 2][0], - ]; - ba.bridge_table.new_bucket(bucket); - // Add the allowed migrations to the migration table - ba.migration_table.table.insert(3 * i, 15 + i); - ba.migration_table.table.insert(3 * i + 1, 15 + i); - ba.migration_table.table.insert(3 * i + 2, 15 + i); - } - // Create the encrypted bridge table - ba.enc_bridge_table(); - - (bdb, ba) -} - -fn trust_promotion(bdb: &BridgeDb, ba: &mut BridgeAuth) -> (cred::Lox, cred::Migration) { - // Issue an open invitation - let inv = bdb.invite(); - - // Use it to get a Lox credential - let (req, state) = open_invite::request(&inv); - let resp = ba.handle_open_invite(req).unwrap(); - let cred = open_invite::handle_response(state, resp, &ba.lox_pub).unwrap(); - assert!(ba.verify_lox(&cred)); - - // Time passes - ba.advance_days(47); - - let (promreq, promstate) = trust_promotion::request(&cred, &ba.lox_pub, ba.today()).unwrap(); - let promresp = ba.handle_trust_promotion(promreq).unwrap(); - let migcred = trust_promotion::handle_response(promstate, promresp).unwrap(); - - (cred, migcred) + assert!(th.ba.verify_lox(&cred)); } #[test] fn test_trust_promotion() { - let (bdb, mut ba) = setup(); + let mut th = TestHarness::new(); - let (_loxcred, migcred) = trust_promotion(&bdb, &mut ba); + let cred = th.open_invite(); + assert!(th.ba.verify_lox(&cred)); + + // Time passes + th.advance_days(47); + + let migcred = th.trust_promotion(&cred); + assert!(th.ba.verify_migration(&migcred)); - assert!(ba.verify_migration(&migcred)); // Check that we can use the to_bucket in the Migration credenital // to read a bucket let (id, key) = bridge_table::from_scalar(migcred.to_bucket).unwrap(); - let encbuckets = ba.enc_bridge_table(); + let encbuckets = th.ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("bucket = {:?}", bucket); - assert!(ba.verify_reachability(&bucket.1.unwrap())); -} - -fn level0_migration(bdb: &BridgeDb, ba: &mut BridgeAuth) -> cred::Lox { - let (loxcred, migcred) = trust_promotion(bdb, ba); - - let (migreq, migstate) = - migration::request(&loxcred, &migcred, &ba.lox_pub, &ba.migration_pub).unwrap(); - let migresp = ba.handle_migration(migreq).unwrap(); - let newloxcred = migration::handle_response(migstate, migresp, &ba.lox_pub).unwrap(); - newloxcred + assert!(th.ba.verify_reachability(&bucket.1.unwrap())); } #[test] fn test_level0_migration() { - let (bdb, mut ba) = setup(); + let mut th = TestHarness::new(); - let newloxcred = level0_migration(&bdb, &mut ba); + let cred = th.open_invite(); + assert!(th.ba.verify_lox(&cred)); - assert!(ba.verify_lox(&newloxcred)); + // Time passes + th.advance_days(47); + + let migcred = th.trust_promotion(&cred); + assert!(th.ba.verify_migration(&migcred)); + + let newloxcred = th.level0_migration(&cred, &migcred); + + assert!(th.ba.verify_lox(&newloxcred)); println!("newloxcred = {:?}", newloxcred); // Check that we can use the credenital to read a bucket let (id, key) = bridge_table::from_scalar(newloxcred.bucket).unwrap(); - let encbuckets = ba.enc_bridge_table(); + let encbuckets = th.ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("bucket = {:?}", bucket); - assert!(ba.verify_reachability(&bucket.1.unwrap())); -} - -fn level_up(ba: &mut BridgeAuth, cred: &cred::Lox) -> cred::Lox { - // Read the bucket in the credential to get today's Bucket - // Reachability credential - let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); - let encbuckets = ba.enc_bridge_table(); - let bucket = - bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); - let reachcred = bucket.1.unwrap(); - - // Use the Bucket Reachability credential to advance to the next - // level - let (req, state) = level_up::request( - &cred, - &reachcred, - &ba.lox_pub, - &ba.reachability_pub, - ba.today(), - ) - .unwrap(); - let resp = ba.handle_level_up(req).unwrap(); - let cred = level_up::handle_response(state, resp, &ba.lox_pub).unwrap(); - cred + assert!(th.ba.verify_reachability(&bucket.1.unwrap())); } #[test] fn test_level_up() { - let (bdb, mut ba) = setup(); - let cred1 = level0_migration(&bdb, &mut ba); + let mut th = TestHarness::new(); + + // Join an untrusted user + let cred = th.open_invite(); + + // Time passes + th.advance_days(47); + + // Go up to level 1 + let migcred = th.trust_promotion(&cred); + let cred1 = th.level0_migration(&cred, &migcred); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes - ba.advance_days(20); + th.advance_days(20); - let cred2 = level_up(&mut ba, &cred1); + let cred2 = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); - assert!(ba.verify_lox(&cred2)); + assert!(th.ba.verify_lox(&cred2)); // Time passes - ba.advance_days(30); + th.advance_days(30); - let cred3 = level_up(&mut ba, &cred2); + let cred3 = th.level_up(&cred2); assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); println!("cred3 = {:?}", cred3); - assert!(ba.verify_lox(&cred3)); + assert!(th.ba.verify_lox(&cred3)); // Time passes - ba.advance_days(60); + th.advance_days(60); - let cred4 = level_up(&mut ba, &cred3); + let cred4 = th.level_up(&cred3); assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); println!("cred4 = {:?}", cred4); - assert!(ba.verify_lox(&cred4)); -} - -fn issue_invite(ba: &mut BridgeAuth, cred: &cred::Lox) -> (cred::Lox, cred::Invitation) { - // Read the bucket in the credential to get today's Bucket - // Reachability credential - let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); - let encbuckets = ba.enc_bridge_table(); - let bucket = - bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); - let reachcred = bucket.1.unwrap(); - - let (req, state) = issue_invite::request( - &cred, - &reachcred, - &ba.lox_pub, - &ba.reachability_pub, - ba.today(), - ) - .unwrap(); - let resp = ba.handle_issue_invite(req).unwrap(); - issue_invite::handle_response(state, resp, &ba.lox_pub, &ba.invitation_pub).unwrap() + assert!(th.ba.verify_lox(&cred4)); } #[test] fn test_issue_invite() { - let (bdb, mut ba) = setup(); - let cred1 = level0_migration(&bdb, &mut ba); + let mut th = TestHarness::new(); + + // Join an untrusted user + let cred = th.open_invite(); + + // Time passes + th.advance_days(47); + + // Go up to level 1 + let migcred = th.trust_promotion(&cred); + let cred1 = th.level0_migration(&cred, &migcred); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes - ba.advance_days(20); + th.advance_days(20); - let cred2 = level_up(&mut ba, &cred1); + // Go up to level 2 + let cred2 = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); - assert!(ba.verify_lox(&cred2)); + assert!(th.ba.verify_lox(&cred2)); - let (cred3, invite) = issue_invite(&mut ba, &cred2); - assert!(ba.verify_lox(&cred3)); - assert!(ba.verify_invitation(&invite)); - println!("cred3 = {:?}", cred3); + // Issue an invitation + let (cred2a, invite) = th.issue_invite(&cred2); + assert!(th.ba.verify_lox(&cred2a)); + assert!(th.ba.verify_invitation(&invite)); + println!("cred2a = {:?}", cred2a); println!("invite = {:?}", invite); } -fn redeem_invite(ba: &mut BridgeAuth, inv: &cred::Invitation) -> cred::Lox { - let (req, state) = redeem_invite::request(&inv, &ba.invitation_pub, ba.today()).unwrap(); - let resp = ba.handle_redeem_invite(req).unwrap(); - redeem_invite::handle_response(state, resp, &ba.lox_pub).unwrap() -} - #[test] fn test_redeem_invite() { - let (bdb, mut ba) = setup(); - let cred1 = level0_migration(&bdb, &mut ba); + let mut th = TestHarness::new(); + + // Join an untrusted user + let cred = th.open_invite(); + + // Time passes + th.advance_days(47); + + // Go up to level 1 + let migcred = th.trust_promotion(&cred); + let cred1 = th.level0_migration(&cred, &migcred); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes - ba.advance_days(20); + th.advance_days(20); - let cred2 = level_up(&mut ba, &cred1); + // Go up to level 2 + let cred2 = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); - assert!(ba.verify_lox(&cred2)); + assert!(th.ba.verify_lox(&cred2)); - let (cred3, invite) = issue_invite(&mut ba, &cred2); - println!("cred3 = {:?}", cred3); - println!("invite = {:?}", invite); + // Issue an invitation to Bob + let (cred2a, bob_invite) = th.issue_invite(&cred2); + assert!(th.ba.verify_lox(&cred2a)); + assert!(th.ba.verify_invitation(&bob_invite)); + println!("cred2a = {:?}", cred2a); + println!("bob_invite = {:?}", bob_invite); // Time passes - ba.advance_days(12); + th.advance_days(12); - let cred4 = redeem_invite(&mut ba, &invite); - assert!(ba.verify_lox(&cred4)); - println!("cred4 = {:?}", cred4); + // Bob joins the system + let bob_cred = th.redeem_invite(&bob_invite); + assert!(th.ba.verify_lox(&bob_cred)); + println!("bob_cred = {:?}", bob_cred); } From 0664dd7b45da28a93bdf6dd5b899b0c714734f3f Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 5 May 2021 13:58:43 -0400 Subject: [PATCH 043/115] API for adding bridges and marking them as unreachable --- crates/lox-library/src/bridge_table.rs | 35 ++-- crates/lox-library/src/lib.rs | 163 ++++++++++++++++-- crates/lox-library/src/migration_table.rs | 31 ++++ .../lox-library/src/proto/trust_promotion.rs | 2 +- crates/lox-library/src/tests.rs | 87 +++++++--- crates/lox-library/tests/tests.rs | 5 +- 6 files changed, 277 insertions(+), 46 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index c341d72..929ee64 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -18,7 +18,7 @@ use curve25519_dalek::ristretto::CompressedRistretto; use curve25519_dalek::ristretto::RistrettoBasepointTable; use curve25519_dalek::scalar::Scalar; use rand::RngCore; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::convert::TryInto; use subtle::ConstantTimeEq; @@ -92,7 +92,7 @@ impl BridgeLine { /// credential if appropriate pub fn bucket_encode( bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET], - reachable: &HashSet, + reachable: &HashMap>, today: u32, bucket_attr: &Scalar, reachability_priv: &IssuerPrivKey, @@ -102,7 +102,7 @@ impl BridgeLine { let mut num_reachable: usize = 0; for bridge in bucket { res[pos..pos + BRIDGE_BYTES].copy_from_slice(&bridge.encode()); - if reachable.contains(bridge) { + if reachable.contains_key(bridge) { num_reachable += 1; } pos += BRIDGE_BYTES; @@ -208,7 +208,13 @@ pub struct BridgeTable { pub keys: Vec<[u8; 16]>, pub buckets: Vec<[BridgeLine; MAX_BRIDGES_PER_BUCKET]>, pub encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>, - pub reachable: HashSet, + /// Individual bridges that are reachable + pub reachable: HashMap>, + /// 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 + /// removed from this set and used for that purpose. + pub spares: HashSet, /// The date the buckets were last encrypted to make the encbucket. /// /// The encbucket must be rebuilt each day so that the Bucket @@ -225,20 +231,27 @@ impl BridgeTable { self.buckets.len() } - /// Append a new bucket to the bridge table - pub fn new_bucket(&mut self, bucket: [BridgeLine; MAX_BRIDGES_PER_BUCKET]) { + /// Append a new bucket to the bridge table, returning its index + pub fn new_bucket(&mut self, bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET]) -> u32 { // Pick a random key to encrypt this bucket let mut rng = rand::thread_rng(); let mut key: [u8; 16] = [0; 16]; rng.fill_bytes(&mut key); self.keys.push(key); - self.buckets.push(bucket); + self.buckets.push(*bucket); + let bucketnum: u32 = (self.buckets.len() - 1).try_into().unwrap(); // Mark the new bridges as available - for b in bucket.iter() { + for (i, b) in bucket.iter().enumerate() { if b.port > 0 { - self.reachable.insert(*b); + if let Some(v) = self.reachable.get_mut(b) { + v.push((bucketnum, i)); + } else { + let v = vec![(bucketnum, i)]; + self.reachable.insert(*b, v); + } } } + bucketnum } /// Create the vector of encrypted buckets from the keys and buckets @@ -321,7 +334,7 @@ mod tests { for _ in 0..20 { let bucket: [BridgeLine; 3] = [BridgeLine::random(), Default::default(), Default::default()]; - btable.new_bucket(bucket); + btable.new_bucket(&bucket); } // And 20 more with three random bridges each for _ in 0..20 { @@ -330,7 +343,7 @@ mod tests { BridgeLine::random(), BridgeLine::random(), ]; - btable.new_bucket(bucket); + btable.new_bucket(&bucket); } let today: u32 = time::OffsetDateTime::now_utc() .date() diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 51961d4..f9a9f1c 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -25,7 +25,7 @@ pub mod migration_table; use sha2::Sha512; use rand::rngs::OsRng; -use rand::RngCore; +use rand::Rng; use std::convert::{TryFrom, TryInto}; use curve25519_dalek::constants as dalek_constants; @@ -38,6 +38,13 @@ use curve25519_dalek::traits::IsIdentity; use ed25519_dalek::{Keypair, PublicKey, Signature, SignatureError, Signer, Verifier}; use subtle::ConstantTimeEq; +use std::collections::HashSet; + +use bridge_table::{ + BridgeLine, BridgeTable, ENC_BUCKET_BYTES, MAX_BRIDGES_PER_BUCKET, MIN_BUCKET_REACHABILITY, +}; +use migration_table::{MigrationTable, MigrationType}; + use lazy_static::lazy_static; lazy_static! { @@ -104,8 +111,8 @@ pub struct BridgeDb { keypair: Keypair, /// The public key for verifying open invitations pub pubkey: PublicKey, - /// The number of open-invitation buckets - num_openinv_buckets: u32, + /// The set of open-invitation buckets + openinv_buckets: HashSet, } /// An open invitation is a [u8; OPENINV_LENGTH] where the first 32 @@ -119,17 +126,27 @@ pub const OPENINV_LENGTH: usize = 32 // the length of the random impl BridgeDb { /// Create the BridgeDb. - pub fn new(num_openinv_buckets: u32) -> Self { + pub fn new() -> Self { let mut csprng = OsRng {}; let keypair = Keypair::generate(&mut csprng); let pubkey = keypair.public; Self { keypair, pubkey, - num_openinv_buckets, + openinv_buckets: Default::default(), } } + /// Insert an open-invitation bucket into the set + pub fn insert_openinv(&mut self, bucket: u32) { + self.openinv_buckets.insert(bucket); + } + + /// Remove an open-invitation bucket from the set + pub fn remove_openinv(&mut self, bucket: u32) { + 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] { @@ -138,9 +155,10 @@ impl BridgeDb { // 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 (mod num_openinv_buckets) and - // serialize it - let bucket_num = rng.next_u32() % self.num_openinv_buckets; + // 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())]; 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)]); @@ -171,6 +189,12 @@ impl BridgeDb { } } +impl Default for BridgeDb { + fn default() -> Self { + Self::new() + } +} + /// The bridge authority. This will typically be a singleton object. #[derive(Debug)] pub struct BridgeAuth { @@ -199,10 +223,11 @@ pub struct BridgeAuth { pub bridgedb_pub: PublicKey, /// The bridge table - bridge_table: bridge_table::BridgeTable, + bridge_table: BridgeTable, - /// The migration table - migration_table: migration_table::MigrationTable, + /// The migration tables + trustup_migration_table: MigrationTable, + blockage_migration_table: MigrationTable, /// Duplicate filter for open invitations openinv_filter: dup_filter::DupFilter, @@ -245,7 +270,8 @@ impl BridgeAuth { invitation_pub, bridgedb_pub, bridge_table: Default::default(), - migration_table: Default::default(), + trustup_migration_table: MigrationTable::new(MigrationType::TrustUpgrade), + blockage_migration_table: MigrationTable::new(MigrationType::Blockage), openinv_filter: Default::default(), id_filter: Default::default(), inv_id_filter: Default::default(), @@ -254,6 +280,117 @@ 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 + /// 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( + &mut self, + bridges: [BridgeLine; MAX_BRIDGES_PER_BUCKET], + bdb: &mut BridgeDb, + ) { + let bnum = self.bridge_table.new_bucket(&bridges); + let mut single = [BridgeLine::default(); MAX_BRIDGES_PER_BUCKET]; + for b in bridges.iter() { + single[0] = *b; + let snum = self.bridge_table.new_bucket(&single); + bdb.insert_openinv(snum); + println!("Adding {} -> {}", snum, bnum); + self.trustup_migration_table.table.insert(snum, bnum); + } + } + + /// Insert a hot spare bucket of bridges + pub fn add_spare_bucket(&mut self, bucket: [BridgeLine; MAX_BRIDGES_PER_BUCKET]) { + let bnum = self.bridge_table.new_bucket(&bucket); + self.bridge_table.spares.insert(bnum); + } + + /// 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 + /// trust upgrade migration for that bucket will be removed and the + /// 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 + /// 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 + /// there was none available. + pub fn bridge_unreachable(&mut self, bridge: &BridgeLine, bdb: &mut BridgeDb) -> bool { + let mut res: bool = true; + let positions = self.bridge_table.reachable.get(bridge); + if let Some(v) = positions { + for (bucketnum, offset) in v.iter() { + // Count how many bridges in this bucket are reachable + let numreachable = self.bridge_table.buckets[*bucketnum as usize] + .iter() + .filter(|br| self.bridge_table.reachable.get(br).is_some()) + .count(); + + // Remove the bridge from the bucket + assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge); + self.bridge_table.buckets[*bucketnum as usize][*offset] = BridgeLine::default(); + + // Is this bucket an open-invitation bucket? + if bdb.openinv_buckets.contains(bucketnum) { + bdb.openinv_buckets.remove(bucketnum); + self.trustup_migration_table.table.remove(bucketnum); + continue; + } + + // Does this removal cause the bucket to go below the + // threshold? + if numreachable != MIN_BUCKET_REACHABILITY { + // No + continue; + } + + // This bucket is now unreachable. Get a spare bucket + if self.bridge_table.spares.is_empty() { + // Uh, oh. No spares available. Just delete any + // migrations leading to this bucket. + res = false; + self.trustup_migration_table + .table + .retain(|_, &mut v| v != *bucketnum); + self.blockage_migration_table + .table + .retain(|_, &mut v| v != *bucketnum); + } else { + // Get the first spare and remove it from the spares + // set. + let spare = *self.bridge_table.spares.iter().next().unwrap(); + self.bridge_table.spares.remove(&spare); + // Add a blockage migration from this bucket to the spare + self.blockage_migration_table + .table + .insert(*bucketnum, spare); + // Remove any trust upgrade migrations to this + // bucket + self.trustup_migration_table + .table + .retain(|_, &mut v| v != *bucketnum); + // Change any blockage migrations with this bucket + // as the destination to the spare + for (_, v) in self.blockage_migration_table.table.iter_mut() { + if *v == *bucketnum { + *v = spare; + } + } + } + } + } + self.bridge_table.reachable.remove(bridge); + + res + } + #[cfg(test)] /// For testing only: manually advance the day by 1 day pub fn advance_day(&mut self) { @@ -282,7 +419,7 @@ impl BridgeAuth { /// Be sure to call this function when you want the latest version /// of the table, since it will put fresh Bucket Reachability /// credentials in the buckets each day. - pub fn enc_bridge_table(&mut self) -> &Vec<[u8; bridge_table::ENC_BUCKET_BYTES]> { + pub fn enc_bridge_table(&mut self) -> &Vec<[u8; ENC_BUCKET_BYTES]> { let today = self.today(); if self.bridge_table.date_last_enc != today { self.bridge_table diff --git a/crates/lox-library/src/migration_table.rs b/crates/lox-library/src/migration_table.rs index 7bf5357..8411568 100644 --- a/crates/lox-library/src/migration_table.rs +++ b/crates/lox-library/src/migration_table.rs @@ -34,10 +34,33 @@ pub const MIGRATION_BYTES: usize = 96; /// The size of an encrypted entry in the returned migration table pub const ENC_MIGRATION_BYTES: usize = MIGRATION_BYTES + 12 + 16; +/// The type of migration table: TrustUpgrade is for migrations from +/// untrusted (level 0) 1-bridge buckets to trusted (level 1) 3-bridge +/// buckets. Blockage is for migrations that drop you down two levels +/// (level 3 to 1, level 4 to 2) because the bridges in your current +/// bucket were blocked. +pub enum MigrationType { + TrustUpgrade, + Blockage, +} + +impl From for Scalar { + /// Convert a MigrationType into the Scalar value that represents + /// it in the Migration credential + fn from(m: MigrationType) -> Self { + match m { + MigrationType::TrustUpgrade => 0u32, + MigrationType::Blockage => 1u32, + } + .into() + } +} + /// The migration table #[derive(Default, Debug)] pub struct MigrationTable { pub table: HashMap, + pub migration_type: Scalar, } /// Create an encrypted Migration credential for returning to the user @@ -143,6 +166,14 @@ pub fn encrypt_cred_ids( } impl MigrationTable { + /// Create a MigrationTable of the given MigrationType + pub fn new(table_type: MigrationType) -> Self { + Self { + table: Default::default(), + migration_type: table_type.into(), + } + } + /// For each entry in the MigrationTable, use encrypt_cred_ids to /// produce an entry in an output HashMap (from labels to encrypted /// Migration credentials). diff --git a/crates/lox-library/src/proto/trust_promotion.rs b/crates/lox-library/src/proto/trust_promotion.rs index 81ebab8..f0e41c4 100644 --- a/crates/lox-library/src/proto/trust_promotion.rs +++ b/crates/lox-library/src/proto/trust_promotion.rs @@ -517,7 +517,7 @@ impl BridgeAuth { Ok(Response { Pk, EncQk, - enc_migration_table: self.migration_table.encrypt_table( + enc_migration_table: self.trustup_migration_table.encrypt_table( &req.id, &self.bridge_table, &Pktable, diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index a960fd9..00ca397 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -13,30 +13,27 @@ struct TestHarness { impl TestHarness { fn new() -> Self { // Create a BridegDb - let bdb = BridgeDb::new(15); + let mut bdb = BridgeDb::new(); // Create a BridgeAuth let mut ba = BridgeAuth::new(bdb.pubkey); - // Make 15 buckets with one random bridge each - for _ in 0..15 { - let bucket: [BridgeLine; 3] = - [BridgeLine::random(), Default::default(), Default::default()]; - ba.bridge_table.new_bucket(bucket); - } - // Make 5 more buckets, each containing 3 of the previously - // created bridges - for i in 0u32..5 { - let iusize = i as usize; - let bucket: [BridgeLine; 3] = [ - ba.bridge_table.buckets[3 * iusize][0], - ba.bridge_table.buckets[3 * iusize + 1][0], - ba.bridge_table.buckets[3 * iusize + 2][0], + // Make 15 open invitation bridges, in 5 sets of 3 + for _ in 0..5 { + let bucket = [ + BridgeLine::random(), + BridgeLine::random(), + BridgeLine::random(), ]; - ba.bridge_table.new_bucket(bucket); - // Add the allowed migrations to the migration table - ba.migration_table.table.insert(3 * i, 15 + i); - ba.migration_table.table.insert(3 * i + 1, 15 + i); - ba.migration_table.table.insert(3 * i + 2, 15 + i); + ba.add_openinv_bridges(bucket, &mut bdb); + } + // Add 5 more hot spare buckets + for _ in 0..5 { + let bucket = [ + BridgeLine::random(), + BridgeLine::random(), + BridgeLine::random(), + ]; + ba.add_spare_bucket(bucket); } // Create the encrypted bridge table ba.enc_bridge_table(); @@ -303,3 +300,53 @@ fn test_redeem_invite() { assert!(th.ba.verify_lox(&bob_cred)); println!("bob_cred = {:?}", bob_cred); } + +#[test] +fn test_mark_unreachable() { + let mut th = TestHarness::new(); + + println!("spares = {:?}", th.ba.bridge_table.spares); + println!("tmig = {:?}", th.ba.trustup_migration_table.table); + println!("bmig = {:?}", th.ba.blockage_migration_table.table); + println!("openinv = {:?}\n", th.bdb.openinv_buckets); + + // Mark a bridge in an untrusted bucket as unreachable + let b6 = th.ba.bridge_table.buckets[6][0]; + th.ba.bridge_unreachable(&b6, &mut th.bdb); + + println!("spares = {:?}", th.ba.bridge_table.spares); + println!("tmig = {:?}", th.ba.trustup_migration_table.table); + println!("bmig = {:?}", th.ba.blockage_migration_table.table); + println!("openinv = {:?}\n", th.bdb.openinv_buckets); + + // Mark another bridge grouped to the same trusted bucket as + // unreachable + let b7 = th.ba.bridge_table.buckets[7][0]; + th.ba.bridge_unreachable(&b7, &mut th.bdb); + + println!("spares = {:?}", th.ba.bridge_table.spares); + println!("tmig = {:?}", th.ba.trustup_migration_table.table); + println!("bmig = {:?}", th.ba.blockage_migration_table.table); + println!("openinv = {:?}\n", th.bdb.openinv_buckets); + + // That will have introduced a blockage migration. Get the target + let target: u32 = *th + .ba + .blockage_migration_table + .table + .iter() + .next() + .unwrap() + .1; + + // Block two of the bridges in that target bucket + let bt1 = th.ba.bridge_table.buckets[target as usize][1]; + let bt2 = th.ba.bridge_table.buckets[target as usize][2]; + th.ba.bridge_unreachable(&bt1, &mut th.bdb); + th.ba.bridge_unreachable(&bt2, &mut th.bdb); + + println!("spares = {:?}", th.ba.bridge_table.spares); + println!("tmig = {:?}", th.ba.trustup_migration_table.table); + println!("bmig = {:?}", th.ba.blockage_migration_table.table); + println!("openinv = {:?}\n", th.bdb.openinv_buckets); +} diff --git a/crates/lox-library/tests/tests.rs b/crates/lox-library/tests/tests.rs index cdd1abd..0416c5b 100644 --- a/crates/lox-library/tests/tests.rs +++ b/crates/lox-library/tests/tests.rs @@ -6,7 +6,10 @@ use curve25519_dalek::scalar::Scalar; #[test] fn test_bridgedb() { - let bdb = BridgeDb::new(20); + let mut bdb = BridgeDb::new(); + for i in &[1u32, 5, 7, 12, 19, 20, 22] { + bdb.insert_openinv(*i); + } let inv = bdb.invite(); println!("{:?}", inv); let res = BridgeDb::verify(inv, bdb.pubkey); From 27773123a3f915b78c65249de7cdad6db48cfc22 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 5 May 2021 15:25:32 -0400 Subject: [PATCH 044/115] Add a migration type attribute to the Migration credential --- crates/lox-library/src/cred.rs | 7 ++++++- crates/lox-library/src/lib.rs | 3 +-- crates/lox-library/src/migration_table.rs | 17 +++++++++++++---- crates/lox-library/src/proto/trust_promotion.rs | 8 +++++++- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/crates/lox-library/src/cred.rs b/crates/lox-library/src/cred.rs index b070854..16b8b12 100644 --- a/crates/lox-library/src/cred.rs +++ b/crates/lox-library/src/cred.rs @@ -10,7 +10,11 @@ use curve25519_dalek::scalar::Scalar; /// 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. +/// given id to switch from bucket from_bucket to bucket to_bucket. The +/// mig_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 been +/// blocked). #[derive(Debug)] pub struct Migration { pub P: RistrettoPoint, @@ -18,6 +22,7 @@ pub struct Migration { pub lox_id: Scalar, pub from_bucket: Scalar, pub to_bucket: Scalar, + pub mig_type: Scalar, } /// The main user credential in the Lox system. diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index f9a9f1c..747a85f 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -249,7 +249,7 @@ impl BridgeAuth { // credential, each with the appropriate number of attributes let lox_priv = IssuerPrivKey::new(6); let lox_pub = IssuerPubKey::new(&lox_priv); - let migration_priv = IssuerPrivKey::new(3); + let migration_priv = IssuerPrivKey::new(4); let migration_pub = IssuerPubKey::new(&migration_priv); let migrationkey_priv = IssuerPrivKey::new(2); let migrationkey_pub = IssuerPubKey::new(&migrationkey_priv); @@ -297,7 +297,6 @@ impl BridgeAuth { single[0] = *b; let snum = self.bridge_table.new_bucket(&single); bdb.insert_openinv(snum); - println!("Adding {} -> {}", snum, bnum); self.trustup_migration_table.table.insert(snum, bnum); } } diff --git a/crates/lox-library/src/migration_table.rs b/crates/lox-library/src/migration_table.rs index 8411568..356dbfd 100644 --- a/crates/lox-library/src/migration_table.rs +++ b/crates/lox-library/src/migration_table.rs @@ -79,6 +79,7 @@ pub fn encrypt_cred( id: &Scalar, from_bucket: &Scalar, to_bucket: &Scalar, + mig_type: &Scalar, Pktable: &RistrettoBasepointTable, migration_priv: &IssuerPrivKey, migrationkey_priv: &IssuerPrivKey, @@ -100,7 +101,8 @@ pub fn encrypt_cred( * (migration_priv.x[0] + migration_priv.x[1] * id + migration_priv.x[2] * from_bucket - + migration_priv.x[3] * to_bucket)) + + migration_priv.x[3] * to_bucket + + migration_priv.x[4] * mig_type)) * Btable; // Serialize (to_bucket, P, Q) @@ -139,7 +141,8 @@ pub fn encrypt_cred( /// Create an encrypted Migration credential for returning to the user /// in the trust promotion protocol, given the ids of the from and to -/// buckets, and using a BridgeTable to get the bucket keys. +/// buckets, and the migration type, and using a BridgeTable to get the +/// bucket keys. /// /// Otherwise the same as encrypt_cred, above, except it returns an /// Option in case the passed ids were invalid. @@ -147,6 +150,7 @@ pub fn encrypt_cred_ids( id: &Scalar, from_id: u32, to_id: u32, + mig_type: &Scalar, bridgetable: &bridge_table::BridgeTable, Pktable: &RistrettoBasepointTable, migration_priv: &IssuerPrivKey, @@ -159,6 +163,7 @@ pub fn encrypt_cred_ids( id, &bridge_table::to_scalar(from_id, fromkey), &bridge_table::to_scalar(to_id, tokey), + mig_type, Pktable, migration_priv, migrationkey_priv, @@ -192,6 +197,7 @@ impl MigrationTable { id, *from_id, *to_id, + &self.migration_type, bridgetable, Pktable, migration_priv, @@ -203,12 +209,14 @@ impl MigrationTable { } /// Decrypt an encrypted Migration credential given Qk, the known -/// attributes id and from_bucket for the Migration credential, and a -/// HashMap mapping labels to ciphertexts. +/// attributes id and from_bucket for the Migration credential as well +/// as the known migration type, and a HashMap mapping labels to +/// ciphertexts. pub fn decrypt_cred( Qk: &RistrettoPoint, lox_id: &Scalar, from_bucket: &Scalar, + mig_type: MigrationType, enc_migration_table: &HashMap<[u8; 16], [u8; ENC_MIGRATION_BYTES]>, ) -> Option { // Compute the hash of (id, from_bucket, Qk) @@ -248,5 +256,6 @@ pub fn decrypt_cred( lox_id: *lox_id, from_bucket: *from_bucket, to_bucket, + mig_type: mig_type.into(), }) } diff --git a/crates/lox-library/src/proto/trust_promotion.rs b/crates/lox-library/src/proto/trust_promotion.rs index f0e41c4..5adf294 100644 --- a/crates/lox-library/src/proto/trust_promotion.rs +++ b/crates/lox-library/src/proto/trust_promotion.rs @@ -542,7 +542,13 @@ pub fn handle_response(state: State, resp: Response) -> Result Ok(m), None => Err(ProofError::VerificationFailure), } From 74bae2cf8eafdad8fecb40ecec8923e2d3bbb0e1 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 5 May 2021 16:28:56 -0400 Subject: [PATCH 045/115] The complete check blockage protocol --- crates/lox-library/src/cred.rs | 10 +- crates/lox-library/src/lib.rs | 1 + crates/lox-library/src/migration_table.rs | 12 +- .../lox-library/src/proto/check_blockage.rs | 355 ++++++++++++++++++ crates/lox-library/src/tests.rs | 71 ++++ 5 files changed, 438 insertions(+), 11 deletions(-) create mode 100644 crates/lox-library/src/proto/check_blockage.rs diff --git a/crates/lox-library/src/cred.rs b/crates/lox-library/src/cred.rs index 16b8b12..a0a320d 100644 --- a/crates/lox-library/src/cred.rs +++ b/crates/lox-library/src/cred.rs @@ -11,10 +11,10 @@ use curve25519_dalek::scalar::Scalar; /// /// This credential authorizes the holder of the Lox credential with the /// given id to switch from bucket from_bucket to bucket to_bucket. The -/// mig_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 been -/// blocked). +/// 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 +/// been blocked). #[derive(Debug)] pub struct Migration { pub P: RistrettoPoint, @@ -22,7 +22,7 @@ pub struct Migration { pub lox_id: Scalar, pub from_bucket: Scalar, pub to_bucket: Scalar, - pub mig_type: Scalar, + pub migration_type: Scalar, } /// The main user credential in the Lox system. diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 747a85f..ee6d182 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -536,6 +536,7 @@ pub fn pt_dbl(P: &RistrettoPoint) -> RistrettoPoint { /// Response. It also adds a handle_* function to the BridgeAuth struct /// that consumes a Request and produces a Result. pub mod proto { + pub mod check_blockage; pub mod issue_invite; pub mod level_up; pub mod migration; diff --git a/crates/lox-library/src/migration_table.rs b/crates/lox-library/src/migration_table.rs index 356dbfd..4a596f1 100644 --- a/crates/lox-library/src/migration_table.rs +++ b/crates/lox-library/src/migration_table.rs @@ -79,7 +79,7 @@ pub fn encrypt_cred( id: &Scalar, from_bucket: &Scalar, to_bucket: &Scalar, - mig_type: &Scalar, + migration_type: &Scalar, Pktable: &RistrettoBasepointTable, migration_priv: &IssuerPrivKey, migrationkey_priv: &IssuerPrivKey, @@ -102,7 +102,7 @@ pub fn encrypt_cred( + migration_priv.x[1] * id + migration_priv.x[2] * from_bucket + migration_priv.x[3] * to_bucket - + migration_priv.x[4] * mig_type)) + + migration_priv.x[4] * migration_type)) * Btable; // Serialize (to_bucket, P, Q) @@ -150,7 +150,7 @@ pub fn encrypt_cred_ids( id: &Scalar, from_id: u32, to_id: u32, - mig_type: &Scalar, + migration_type: &Scalar, bridgetable: &bridge_table::BridgeTable, Pktable: &RistrettoBasepointTable, migration_priv: &IssuerPrivKey, @@ -163,7 +163,7 @@ pub fn encrypt_cred_ids( id, &bridge_table::to_scalar(from_id, fromkey), &bridge_table::to_scalar(to_id, tokey), - mig_type, + migration_type, Pktable, migration_priv, migrationkey_priv, @@ -216,7 +216,7 @@ pub fn decrypt_cred( Qk: &RistrettoPoint, lox_id: &Scalar, from_bucket: &Scalar, - mig_type: MigrationType, + migration_type: MigrationType, enc_migration_table: &HashMap<[u8; 16], [u8; ENC_MIGRATION_BYTES]>, ) -> Option { // Compute the hash of (id, from_bucket, Qk) @@ -256,6 +256,6 @@ pub fn decrypt_cred( lox_id: *lox_id, from_bucket: *from_bucket, to_bucket, - mig_type: mig_type.into(), + migration_type: migration_type.into(), }) } diff --git a/crates/lox-library/src/proto/check_blockage.rs b/crates/lox-library/src/proto/check_blockage.rs new file mode 100644 index 0000000..a60958c --- /dev/null +++ b/crates/lox-library/src/proto/check_blockage.rs @@ -0,0 +1,355 @@ +/*! A module for the protocol for the user to check for the availability +of a migration credential they can use in order to move to a new bucket +if theirs has been blocked. + +The user presents their current Lox credential: +- id: revealed +- bucket: blinded +- trust_level: revealed to be 3 or above +- level_since: blinded +- invites_remaining: blinded +- blockages: blinded + +They are allowed to to this as long as they are level 3 or above. If +they have too many blockages (but are level 3 or above), they will be +allowed to perform this migration, but will not be able to advance to +level 3 in their new bucket, so this will be their last allowed +migration without rejoining the system either with a new invitation or +an open invitation. + +They will receive in return the encrypted MAC (Pk, EncQk) for their +implicit Migration Key credential with attributes id and bucket, +along with a HashMap of encrypted Migration credentials. For each +(from_i, to_i) in the BA's migration list, there will be an entry in +the HashMap with key H1(id, from_attr_i, Qk_i) and value +Enc_{H2(id, from_attr_i, Qk_i)}(to_attr_i, P_i, Q_i). Here H1 and H2 +are the first 16 bytes and the second 16 bytes respectively of the +SHA256 hash of the input, P_i and Q_i are a MAC on the Migration +credential with attributes id, from_attr_i, and to_attr_i. Qk_i is the +value EncQk would decrypt to if bucket were equal to from_attr_i. */ + +use curve25519_dalek::ristretto::RistrettoBasepointTable; +use curve25519_dalek::ristretto::RistrettoPoint; +use curve25519_dalek::scalar::Scalar; +use curve25519_dalek::traits::IsIdentity; + +use zkp::CompactProof; +use zkp::ProofError; +use zkp::Transcript; + +use std::collections::HashMap; + +use super::super::cred; +use super::super::dup_filter::SeenType; +use super::super::migration_table; +use super::super::scalar_u32; +use super::super::{BridgeAuth, IssuerPubKey}; +use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; + +/// The minimum trust level a Lox credential must have to be allowed to +/// perform this protocol. +pub const MIN_TRUST_LEVEL: u32 = 3; + +pub struct Request { + // Fields for blind showing the Lox credential + P: RistrettoPoint, + id: Scalar, + CBucket: RistrettoPoint, + level: Scalar, + CSince: RistrettoPoint, + CInvRemain: RistrettoPoint, + CBlockages: RistrettoPoint, + CQ: RistrettoPoint, + + // Fields for user blinding of the Migration Key credential + D: RistrettoPoint, + EncBucket: (RistrettoPoint, RistrettoPoint), + + // The combined ZKP + piUser: CompactProof, +} + +#[derive(Debug)] +pub struct State { + d: Scalar, + D: RistrettoPoint, + EncBucket: (RistrettoPoint, RistrettoPoint), + id: Scalar, + bucket: Scalar, +} + +#[derive(Debug)] +pub struct Response { + // The encrypted MAC for the Migration Key credential + Pk: RistrettoPoint, + EncQk: (RistrettoPoint, RistrettoPoint), + + // A table of encrypted Migration credentials; the encryption keys + // are formed from the possible values of Qk (the decrypted form of + // EncQk) + enc_migration_table: HashMap<[u8; 16], [u8; migration_table::ENC_MIGRATION_BYTES]>, +} + +define_proof! { + requestproof, + "Check Blockage Request", + (bucket, since, invremain, blockages, zbucket, zsince, zinvremain, + zblockages, negzQ, + d, ebucket), + (P, CBucket, CSince, CInvRemain, CBlockages, V, Xbucket, Xsince, + Xinvremain, Xblockages, + D, EncBucket0, EncBucket1), + (A, B): + // Blind showing of the Lox credential + CBucket = (bucket*P + zbucket*A), + CSince = (since*P + zsince*A), + CInvRemain = (invremain*P + zinvremain*A), + CBlockages = (blockages*P + zblockages*A), + V = (zbucket*Xbucket + zsince*Xsince + zinvremain*Xinvremain + + zblockages*Xblockages + negzQ*A), + // User blinding of the Migration Key credential + D = (d*B), + EncBucket0 = (ebucket*B), + EncBucket1 = (bucket*B + ebucket*D) +} + +pub fn request( + lox_cred: &cred::Lox, + lox_pub: &IssuerPubKey, +) -> Result<(Request, State), ProofError> { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + // Ensure the credential can be correctly shown: it must be the case + // that trust_level >= MIN_TRUST_LEVEL + let level: u32 = match scalar_u32(&lox_cred.trust_level) { + Some(v) => v, + None => return Err(ProofError::VerificationFailure), + }; + if level < MIN_TRUST_LEVEL { + return Err(ProofError::VerificationFailure); + } + + // Blind showing the Lox credential + + // Reblind P and Q + let mut rng = rand::thread_rng(); + let t = Scalar::random(&mut rng); + let P = t * lox_cred.P; + let Q = t * lox_cred.Q; + + // Form Pedersen commitments to the blinded attributes + let zbucket = Scalar::random(&mut rng); + let zsince = Scalar::random(&mut rng); + let zinvremain = Scalar::random(&mut rng); + let zblockages = Scalar::random(&mut rng); + let CBucket = lox_cred.bucket * P + &zbucket * Atable; + let CSince = lox_cred.level_since * P + &zsince * Atable; + let CInvRemain = lox_cred.invites_remaining * P + &zinvremain * Atable; + let CBlockages = lox_cred.blockages * P + &zblockages * Atable; + + // Form a Pedersen commitment to the MAC Q + // We flip the sign of zQ from that of the Hyphae paper so that + // the ZKP has a "+" instead of a "-", as that's what the zkp + // macro supports. + let negzQ = Scalar::random(&mut rng); + let CQ = Q - &negzQ * Atable; + + // Compute the "error factor" + let V = zbucket * lox_pub.X[2] + + zsince * lox_pub.X[4] + + zinvremain * lox_pub.X[5] + + zblockages * lox_pub.X[6] + + &negzQ * Atable; + + // User blinding the Migration Key credential + + // Pick an ElGamal keypair + let d = Scalar::random(&mut rng); + let D = &d * Btable; + + // Encrypt the attributes to be blinded (each times the + // basepoint B) to the public key we just created + let ebucket = Scalar::random(&mut rng); + let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D); + + // Construct the proof + let mut transcript = Transcript::new(b"check blockage request"); + let piUser = requestproof::prove_compact( + &mut transcript, + requestproof::ProveAssignments { + A: &A, + B: &B, + P: &P, + CBucket: &CBucket, + CSince: &CSince, + CInvRemain: &CInvRemain, + CBlockages: &CBlockages, + V: &V, + Xbucket: &lox_pub.X[2], + Xsince: &lox_pub.X[4], + Xinvremain: &lox_pub.X[5], + Xblockages: &lox_pub.X[6], + D: &D, + EncBucket0: &EncBucket.0, + EncBucket1: &EncBucket.1, + bucket: &lox_cred.bucket, + since: &lox_cred.level_since, + invremain: &lox_cred.invites_remaining, + blockages: &lox_cred.blockages, + zbucket: &zbucket, + zsince: &zsince, + zinvremain: &zinvremain, + zblockages: &zblockages, + negzQ: &negzQ, + d: &d, + ebucket: &ebucket, + }, + ) + .0; + + Ok(( + Request { + P, + id: lox_cred.id, + CBucket, + level: lox_cred.trust_level, + CSince, + CInvRemain, + CBlockages, + CQ, + D, + EncBucket, + piUser, + }, + State { + d, + D, + EncBucket, + id: lox_cred.id, + bucket: lox_cred.bucket, + }, + )) +} + +impl BridgeAuth { + /// Receive a check blockage request + pub fn handle_check_blockage(&mut self, req: Request) -> Result { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + let level: u32 = match scalar_u32(&req.level) { + Some(v) => v, + None => return Err(ProofError::VerificationFailure), + }; + + if req.P.is_identity() || level < MIN_TRUST_LEVEL { + return Err(ProofError::VerificationFailure); + } + + // Recompute the "error factor" using knowledge of our own + // (the issuer's) private key instead of knowledge of the + // hidden attributes + let Vprime = + (self.lox_priv.x[0] + self.lox_priv.x[1] * req.id + self.lox_priv.x[3] * req.level) + * req.P + + self.lox_priv.x[2] * req.CBucket + + self.lox_priv.x[4] * req.CSince + + self.lox_priv.x[5] * req.CInvRemain + + self.lox_priv.x[6] * req.CBlockages + - req.CQ; + + // Verify the ZKP + let mut transcript = Transcript::new(b"check blockage request"); + requestproof::verify_compact( + &req.piUser, + &mut transcript, + requestproof::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P: &req.P.compress(), + CBucket: &req.CBucket.compress(), + CSince: &req.CSince.compress(), + CInvRemain: &req.CInvRemain.compress(), + CBlockages: &req.CBlockages.compress(), + V: &Vprime.compress(), + Xbucket: &self.lox_pub.X[2].compress(), + Xsince: &self.lox_pub.X[4].compress(), + Xinvremain: &self.lox_pub.X[5].compress(), + Xblockages: &self.lox_pub.X[6].compress(), + D: &req.D.compress(), + EncBucket0: &req.EncBucket.0.compress(), + EncBucket1: &req.EncBucket.1.compress(), + }, + )?; + + // Ensure the id has not been seen before in the general id + // filter, but do not add it, so that the user can potentially + // run this protocol multiple times. + if self.id_filter.check(&req.id) == SeenType::Seen { + return Err(ProofError::VerificationFailure); + } + + // Compute the encrypted MAC (Pk, EncQk) for the Migration Key + // credential. + + // Compute the MAC on the visible attributes + let mut rng = rand::thread_rng(); + let b = Scalar::random(&mut rng); + let Pk = &b * Btable; + let Pktable = RistrettoBasepointTable::create(&Pk); + let Qid = &(self.migrationkey_priv.x[0] + self.migrationkey_priv.x[1] * req.id) * &Pktable; + + // El Gamal encrypt it to the public key req.D + let s = Scalar::random(&mut rng); + let EncQkid = (&s * Btable, Qid + s * req.D); + + // Homomorphically compute the part of the MAC corresponding to + // the blinded attributes + let tbucket = self.migrationkey_priv.x[2] * b; + let EncQkBucket = (tbucket * req.EncBucket.0, tbucket * req.EncBucket.1); + + let EncQk = (EncQkid.0 + EncQkBucket.0, EncQkid.1 + EncQkBucket.1); + + Ok(Response { + Pk, + EncQk, + enc_migration_table: self.blockage_migration_table.encrypt_table( + &req.id, + &self.bridge_table, + &Pktable, + &self.migration_priv, + &self.migrationkey_priv, + ), + }) + } +} + +/// Handle the response to the request, producing a Migration credential +/// if successful. +/// +/// The Migration credential can then be used in the migration protocol +/// to actually change buckets +pub fn handle_response(state: State, resp: Response) -> Result { + if resp.Pk.is_identity() { + return Err(ProofError::VerificationFailure); + } + + // Decrypt the MAC on the Migration Key credential + let Qk = resp.EncQk.1 - (state.d * resp.EncQk.0); + + // Use Qk to locate and decrypt the Migration credential + match migration_table::decrypt_cred( + &Qk, + &state.id, + &state.bucket, + migration_table::MigrationType::Blockage, + &resp.enc_migration_table, + ) { + Some(m) => Ok(m), + None => Err(ProofError::VerificationFailure), + } +} diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 00ca397..00e1987 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -120,6 +120,12 @@ impl TestHarness { let resp = self.ba.handle_redeem_invite(req).unwrap(); redeem_invite::handle_response(state, resp, &self.ba.lox_pub).unwrap() } + + fn check_blockage(&mut self, cred: &cred::Lox) -> cred::Migration { + let (req, state) = check_blockage::request(&cred, &self.ba.lox_pub).unwrap(); + let resp = self.ba.handle_check_blockage(req).unwrap(); + check_blockage::handle_response(state, resp).unwrap() + } } #[test] @@ -350,3 +356,68 @@ fn test_mark_unreachable() { println!("bmig = {:?}", th.ba.blockage_migration_table.table); println!("openinv = {:?}\n", th.bdb.openinv_buckets); } + +#[test] +fn test_check_blockage() { + let mut th = TestHarness::new(); + + // Join an untrusted user + let cred = th.open_invite(); + + // Time passes + th.advance_days(47); + + // Go up to level 1 + let migcred = th.trust_promotion(&cred); + let cred1 = th.level0_migration(&cred, &migcred); + assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); + + // Time passes + th.advance_days(20); + + // Go up to level 2 + let cred2 = th.level_up(&cred1); + assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); + println!("cred2 = {:?}", cred2); + assert!(th.ba.verify_lox(&cred2)); + + // Time passes + th.advance_days(29); + + // Go up to level 3 + let cred3 = th.level_up(&cred2); + assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); + println!("cred3 = {:?}", cred3); + assert!(th.ba.verify_lox(&cred3)); + + // Get our bridges + let (id, key) = bridge_table::from_scalar(cred3.bucket).unwrap(); + let encbuckets = th.ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); + // We should have a Bridge Reachability credential + assert!(bucket.1.is_some()); + + // Oh, no! Two of our bridges are blocked! + th.ba.bridge_unreachable(&bucket.0[0], &mut th.bdb); + th.ba.bridge_unreachable(&bucket.0[2], &mut th.bdb); + + println!("spares = {:?}", th.ba.bridge_table.spares); + println!("tmig = {:?}", th.ba.trustup_migration_table.table); + println!("bmig = {:?}", th.ba.blockage_migration_table.table); + println!("openinv = {:?}\n", th.bdb.openinv_buckets); + + // Time passes + th.advance_days(1); + + let encbuckets2 = th.ba.enc_bridge_table(); + let bucket2 = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets2[id as usize]).unwrap(); + // We should no longer have a Bridge Reachability credential + assert!(bucket2.1.is_none()); + + // See about getting a Migration credential for the blockage + let migration = th.check_blockage(&cred3); + + println!("migration = {:?}", migration); +} From 4bb77d16e415c24f0cd3ed12882f5990e58c68af Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 5 May 2021 16:33:52 -0400 Subject: [PATCH 046/115] Be consistent about the ordering of the parameters in the ZKPs Particularly D --- crates/lox-library/src/proto/migration.rs | 4 ++-- crates/lox-library/src/proto/open_invite.rs | 8 ++++---- crates/lox-library/src/proto/trust_promotion.rs | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/lox-library/src/proto/migration.rs b/crates/lox-library/src/proto/migration.rs index 0402f8a..8af5672 100644 --- a/crates/lox-library/src/proto/migration.rs +++ b/crates/lox-library/src/proto/migration.rs @@ -117,11 +117,11 @@ define_proof! { V_mig = (zfrombucket*Xfrombucket + ztobucket*Xtobucket + negzQ_mig*A), // User blinding of the Lox credential to be issued; note the use of // the same "tobucket" secret variable + D = (d*B), EncIdClient0 = (eid_client*B), EncIdClient1 = (id_client*B + eid_client*D), EncBucket0 = (ebucket*B), - EncBucket1 = (tobucket*B + ebucket*D), - D = (d*B) + EncBucket1 = (tobucket*B + ebucket*D) } define_proof! { diff --git a/crates/lox-library/src/proto/open_invite.rs b/crates/lox-library/src/proto/open_invite.rs index d2ee731..3d7b20c 100644 --- a/crates/lox-library/src/proto/open_invite.rs +++ b/crates/lox-library/src/proto/open_invite.rs @@ -62,11 +62,11 @@ define_proof! { userblinding, "Open Invitation User Blinding", (d, eid_client, id_client), - (EncIdClient0, EncIdClient1, D), + (D, EncIdClient0, EncIdClient1), (B) : + D = (d*B), EncIdClient0 = (eid_client*B), - EncIdClient1 = (id_client*B + eid_client*D), - D = (d*B) + EncIdClient1 = (id_client*B + eid_client*D) } // The issuing ZKP @@ -113,9 +113,9 @@ pub fn request(invite: &[u8; OPENINV_LENGTH]) -> (Request, State) { &mut transcript, userblinding::ProveAssignments { B: &B, + D: &D, EncIdClient0: &EncIdClient.0, EncIdClient1: &EncIdClient.1, - D: &D, d: &d, eid_client: &eid_client, id_client: &id_client, diff --git a/crates/lox-library/src/proto/trust_promotion.rs b/crates/lox-library/src/proto/trust_promotion.rs index 5adf294..bced670 100644 --- a/crates/lox-library/src/proto/trust_promotion.rs +++ b/crates/lox-library/src/proto/trust_promotion.rs @@ -123,7 +123,7 @@ define_proof! { wg0, wg1, wg2, wg3, wg4, wg5, wg6, wg7, wg8, yg0, yg1, yg2, yg3, yg4, yg5, yg6, yg7, yg8), (P, CBucket, CSince, V, Xbucket, Xsince, - EncBucket0, EncBucket1, D, + D, EncBucket0, EncBucket1, CG0, CG1, CG2, CG3, CG4, CG5, CG6, CG7, CG8, CG0sq, CG1sq, CG2sq, CG3sq, CG4sq, CG5sq, CG6sq, CG7sq, CG8sq), (A, B): @@ -132,9 +132,9 @@ define_proof! { CSince = (since*P + zsince*A), V = (zbucket*Xbucket + zsince*Xsince + negzQ*A), // User blinding of the Migration Key credential + D = (d*B), EncBucket0 = (ebucket*B), EncBucket1 = (bucket*B + ebucket*D), - D = (d*B), // Prove CSince encodes a value at least UNTRUSTED_INTERVAL // days ago (and technically at most UNTRUSTED_INTERVAL+511 days // ago): first prove each of g0, ..., g8 is a bit by proving that @@ -303,9 +303,9 @@ pub fn request( V: &V, Xbucket: &lox_pub.X[2], Xsince: &lox_pub.X[4], + D: &D, EncBucket0: &EncBucket.0, EncBucket1: &EncBucket.1, - D: &D, CG0: &CG0, CG1: &CG1, CG2: &CG2, @@ -460,9 +460,9 @@ impl BridgeAuth { V: &Vprime.compress(), Xbucket: &self.lox_pub.X[2].compress(), Xsince: &self.lox_pub.X[4].compress(), + D: &req.D.compress(), EncBucket0: &req.EncBucket.0.compress(), EncBucket1: &req.EncBucket.1.compress(), - D: &req.D.compress(), CG0: &CG0prime.compress(), CG1: &req.CG1.compress(), CG2: &req.CG2.compress(), From 596cf10ea58b9adbfa181e77b7f1d5a9b8c26ea3 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 5 May 2021 18:21:09 -0400 Subject: [PATCH 047/115] The complete blockage migration protocol --- crates/lox-library/src/lib.rs | 1 + .../src/proto/blockage_migration.rs | 682 ++++++++++++++++++ crates/lox-library/src/proto/migration.rs | 11 +- crates/lox-library/src/tests.rs | 16 +- 4 files changed, 703 insertions(+), 7 deletions(-) create mode 100644 crates/lox-library/src/proto/blockage_migration.rs diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index ee6d182..253313a 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -536,6 +536,7 @@ pub fn pt_dbl(P: &RistrettoPoint) -> RistrettoPoint { /// Response. It also adds a handle_* function to the BridgeAuth struct /// that consumes a Request and produces a Result. pub mod proto { + pub mod blockage_migration; pub mod check_blockage; pub mod issue_invite; pub mod level_up; diff --git a/crates/lox-library/src/proto/blockage_migration.rs b/crates/lox-library/src/proto/blockage_migration.rs new file mode 100644 index 0000000..694ad4e --- /dev/null +++ b/crates/lox-library/src/proto/blockage_migration.rs @@ -0,0 +1,682 @@ +/*! A module for the protocol for the user of trust level 3 or higher to +migrate from one bucket to another because their current bucket has been +blocked. Their trust level will go down by 2. + +The user presents their current Lox credential: + +- id: revealed +- bucket: blinded +- trust_level: revealed to be 3 or higher +- level_since: blinded +- invites_remaining: blinded +- blockages: blinded + +and a Migration credential: + +- id: revealed as the same as the Lox credential id above +- from_bucket: blinded, but proved in ZK that it's the same as the + bucket in the Lox credential above +- to_bucket: blinded + +and a new Lox credential to be issued: + +- id: jointly chosen by the user and BA +- bucket: blinded, but proved in ZK that it's the same as the to_bucket + in the Migration credential above +- trust_level: revealed to be 2 less than the trust_level above +- level_since: today +- invites_remaining: revealed to be LEVEL_INVITATIONS for the new trust + level [Actually, there's a bug in the zkp crate that's triggered when + a public value is 0 (the identity element of the Ristretto group), so + we treat this field as blinded, but the _server_ encrypts the value.] +- blockages: blinded, but proved in ZK that it's one more than the + blockages above + +*/ + +use curve25519_dalek::ristretto::RistrettoBasepointTable; +use curve25519_dalek::ristretto::RistrettoPoint; +use curve25519_dalek::scalar::Scalar; +use curve25519_dalek::traits::IsIdentity; + +use zkp::CompactProof; +use zkp::ProofError; +use zkp::Transcript; + +use super::super::cred; +use super::super::dup_filter::SeenType; +use super::super::migration_table::MigrationType; +use super::super::scalar_u32; +use super::super::{BridgeAuth, IssuerPubKey}; +use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; +use super::check_blockage::MIN_TRUST_LEVEL; +use super::level_up::LEVEL_INVITATIONS; + +pub struct Request { + // Fields for blind showing the Lox credential + P_lox: RistrettoPoint, + id: Scalar, + CBucket: RistrettoPoint, + trust_level: Scalar, + CSince: RistrettoPoint, + CInvRemain: RistrettoPoint, + CBlockages: RistrettoPoint, + CQ_lox: RistrettoPoint, + + // Fields for blind showing the Migration credential + P_mig: RistrettoPoint, + CFromBucket: RistrettoPoint, + CToBucket: RistrettoPoint, + CQ_mig: RistrettoPoint, + + // Fields for user blinding of the Lox credential to be issued + D: RistrettoPoint, + EncIdClient: (RistrettoPoint, RistrettoPoint), + EncBucket: (RistrettoPoint, RistrettoPoint), + EncBlockages: (RistrettoPoint, RistrettoPoint), + + // The combined ZKP + piUser: CompactProof, +} + +#[derive(Debug)] +pub struct State { + d: Scalar, + D: RistrettoPoint, + EncIdClient: (RistrettoPoint, RistrettoPoint), + EncBucket: (RistrettoPoint, RistrettoPoint), + EncBlockages: (RistrettoPoint, RistrettoPoint), + id_client: Scalar, + to_bucket: Scalar, + trust_level: Scalar, + blockages: Scalar, +} + +pub struct Response { + // The new attributes; the trust_level and invites_remaining are + // implicit + level_since: Scalar, + + // The fields for the new Lox credential + P: RistrettoPoint, + EncQ: (RistrettoPoint, RistrettoPoint), + EncInvRemain: (RistrettoPoint, RistrettoPoint), + id_server: Scalar, + TId: RistrettoPoint, + TBucket: RistrettoPoint, + TInvRemain: RistrettoPoint, + TBlockages: RistrettoPoint, + + // The ZKP + piBlindIssue: CompactProof, +} + +define_proof! { + requestproof, + "Blockage Migration Request", + (bucket, since, invremain, blockages, zbucket, zsince, zinvremain, + zblockages, negzQ_lox, + tobucket, zfrombucket, ztobucket, negzQ_mig, + d, eid_client, ebucket, eblockages, id_client), + (P_lox, CBucket, CSince, CInvRemain, CBlockages, V_lox, Xbucket, + Xsince, Xinvremain, Xblockages, + P_mig, CFromBucket, CToBucket, V_mig, Xfrombucket, Xtobucket, + D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1, + EncBlockages0, EncBlockages1_minus_B), + (A, B): + // Blind showing of the Lox credential + CBucket = (bucket*P_lox + zbucket*A), + CSince = (since*P_lox + zsince*A), + CInvRemain = (invremain*P_lox + zinvremain*A), + CBlockages = (blockages*P_lox + zblockages*A), + V_lox = (zbucket*Xbucket + zsince*Xsince + zinvremain*Xinvremain + + zblockages*Xblockages + negzQ_lox*A), + // Blind showing of the Migration credential; note the use of the + // same "bucket" secret variable + CFromBucket = (bucket*P_mig + zfrombucket*A), + CToBucket = (tobucket*P_mig + ztobucket*A), + V_mig = (zfrombucket*Xfrombucket + ztobucket*Xtobucket + negzQ_mig*A), + // User blinding of the Lox credential to be issued; note the use of + // the same "tobucket" secret variable + D = (d*B), + EncIdClient0 = (eid_client*B), + EncIdClient1 = (id_client*B + eid_client*D), + EncBucket0 = (ebucket*B), + EncBucket1 = (tobucket*B + ebucket*D), + EncBlockages0 = (eblockages*B), + EncBlockages1_minus_B = (blockages*B + eblockages*D) +} + +define_proof! { + blindissue, + "Blockage Migration Blind Issuing", + (x0, x0tilde, xid, xbucket, xlevel, xsince, xinvremain, xblockages, + s, b, tid, tbucket, tinvremain, tblockages), + (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xlevel, Xsince, Xinvremain, + Xblockages, Plevel, Psince, TId, TBucket, TInvRemain, TBlockages, + D, EncId0, EncId1, EncBucket0, EncBucket1, EncInvRemain0, + EncInvRemain1, EncBlockages0, EncBlockages1), + (A, B): + Xid = (xid*A), + Xlevel = (xlevel*A), + Xbucket = (xbucket*A), + Xsince = (xsince*A), + Xinvremain = (xinvremain*A), + Xblockages = (xblockages*A), + X0 = (x0*B + x0tilde*A), + P = (b*B), + TId = (b*Xid), + TId = (tid*A), + TBucket = (b*Xbucket), + TBucket = (tbucket*A), + TInvRemain = (b*Xinvremain), + TInvRemain = (tinvremain*A), + TBlockages = (b*Xblockages), + TBlockages = (tblockages*A), + EncQ0 = (s*B + tid*EncId0 + tbucket*EncBucket0 + + tinvremain*EncInvRemain0 + tblockages*EncBlockages0), + EncQ1 = (s*D + tid*EncId1 + tbucket*EncBucket1 + + tinvremain*EncInvRemain1 + tblockages*EncBlockages1 + + x0*P + xlevel*Plevel + xsince*Psince) +} + +pub fn request( + lox_cred: &cred::Lox, + migration_cred: &cred::Migration, + lox_pub: &IssuerPubKey, + migration_pub: &IssuerPubKey, +) -> Result<(Request, State), ProofError> { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + // Ensure that the credenials can be correctly shown; that is, the + // ids match and the Lox credential bucket matches the Migration + // credential from_bucket + if lox_cred.id != migration_cred.lox_id || lox_cred.bucket != migration_cred.from_bucket { + return Err(ProofError::VerificationFailure); + } + + // The trust level must be at least MIN_TRUST_LEVEL + let level: u32 = match scalar_u32(&lox_cred.trust_level) { + Some(v) => v, + None => return Err(ProofError::VerificationFailure), + }; + if level < MIN_TRUST_LEVEL { + return Err(ProofError::VerificationFailure); + } + + // Blind showing the Lox credential + + // Reblind P and Q + let mut rng = rand::thread_rng(); + let t_lox = Scalar::random(&mut rng); + let P_lox = t_lox * lox_cred.P; + let Q_lox = t_lox * lox_cred.Q; + + // Form Pedersen commitments to the blinded attributes + let zbucket = Scalar::random(&mut rng); + let zsince = Scalar::random(&mut rng); + let zinvremain = Scalar::random(&mut rng); + let zblockages = Scalar::random(&mut rng); + let CBucket = lox_cred.bucket * P_lox + &zbucket * Atable; + let CSince = lox_cred.level_since * P_lox + &zsince * Atable; + let CInvRemain = lox_cred.invites_remaining * P_lox + &zinvremain * Atable; + let CBlockages = lox_cred.blockages * P_lox + &zblockages * Atable; + + // Form a Pedersen commitment to the MAC Q + // We flip the sign of zQ from that of the Hyphae paper so that + // the ZKP has a "+" instead of a "-", as that's what the zkp + // macro supports. + let negzQ_lox = Scalar::random(&mut rng); + let CQ_lox = Q_lox - &negzQ_lox * Atable; + + // Compute the "error factor" + let V_lox = zbucket * lox_pub.X[2] + + zsince * lox_pub.X[4] + + zinvremain * lox_pub.X[5] + + zblockages * lox_pub.X[6] + + &negzQ_lox * Atable; + + // Blind showing the Migration credential + + // Reblind P and Q + let t_mig = Scalar::random(&mut rng); + let P_mig = t_mig * migration_cred.P; + let Q_mig = t_mig * migration_cred.Q; + + // Form Pedersen commitments to the blinded attributes + let zfrombucket = Scalar::random(&mut rng); + let ztobucket = Scalar::random(&mut rng); + let CFromBucket = migration_cred.from_bucket * P_mig + &zfrombucket * Atable; + let CToBucket = migration_cred.to_bucket * P_mig + &ztobucket * Atable; + + // Form a Pedersen commitment to the MAC Q + // We flip the sign of zQ from that of the Hyphae paper so that + // the ZKP has a "+" instead of a "-", as that's what the zkp + // macro supports. + let negzQ_mig = Scalar::random(&mut rng); + let CQ_mig = Q_mig - &negzQ_mig * Atable; + + // Compute the "error factor" + let V_mig = + zfrombucket * migration_pub.X[2] + ztobucket * migration_pub.X[3] + &negzQ_mig * Atable; + + // User blinding for the Lox certificate to be issued + + // Pick an ElGamal keypair + let d = Scalar::random(&mut rng); + let D = &d * Btable; + + // Pick a random client component of the id + let id_client = Scalar::random(&mut rng); + + // Encrypt it (times the basepoint B) to the ElGamal public key D we + // just created + let eid_client = Scalar::random(&mut rng); + let EncIdClient = (&eid_client * Btable, &id_client * Btable + eid_client * D); + + // Encrypt the other blinded attributes (times B) to D as well + let ebucket = Scalar::random(&mut rng); + let EncBucket = ( + &ebucket * Btable, + &migration_cred.to_bucket * Btable + ebucket * D, + ); + let eblockages = Scalar::random(&mut rng); + let new_blockages = lox_cred.blockages + Scalar::one(); + let EncBlockages = ( + &eblockages * Btable, + &new_blockages * Btable + eblockages * D, + ); + + // Construct the proof + let mut transcript = Transcript::new(b"blockage migration request"); + let piUser = requestproof::prove_compact( + &mut transcript, + requestproof::ProveAssignments { + A: &A, + B: &B, + P_lox: &P_lox, + CBucket: &CBucket, + CSince: &CSince, + CInvRemain: &CInvRemain, + CBlockages: &CBlockages, + V_lox: &V_lox, + Xbucket: &lox_pub.X[2], + Xsince: &lox_pub.X[4], + Xinvremain: &lox_pub.X[5], + Xblockages: &lox_pub.X[6], + P_mig: &P_mig, + CFromBucket: &CFromBucket, + CToBucket: &CToBucket, + V_mig: &V_mig, + Xfrombucket: &migration_pub.X[2], + Xtobucket: &migration_pub.X[3], + D: &D, + EncIdClient0: &EncIdClient.0, + EncIdClient1: &EncIdClient.1, + EncBucket0: &EncBucket.0, + EncBucket1: &EncBucket.1, + EncBlockages0: &EncBlockages.0, + EncBlockages1_minus_B: &(EncBlockages.1 - B), + bucket: &lox_cred.bucket, + since: &lox_cred.level_since, + invremain: &lox_cred.invites_remaining, + blockages: &lox_cred.blockages, + zbucket: &zbucket, + zsince: &zsince, + zinvremain: &zinvremain, + zblockages: &zblockages, + negzQ_lox: &negzQ_lox, + tobucket: &migration_cred.to_bucket, + zfrombucket: &zfrombucket, + ztobucket: &ztobucket, + negzQ_mig: &negzQ_mig, + d: &d, + eid_client: &eid_client, + ebucket: &ebucket, + eblockages: &eblockages, + id_client: &id_client, + }, + ) + .0; + + Ok(( + Request { + P_lox, + id: lox_cred.id, + CBucket, + trust_level: lox_cred.trust_level, + CSince, + CInvRemain, + CBlockages, + CQ_lox, + P_mig, + CFromBucket, + CToBucket, + CQ_mig, + D, + EncIdClient, + EncBucket, + EncBlockages, + piUser, + }, + State { + d, + D, + EncIdClient, + EncBucket, + EncBlockages, + id_client, + to_bucket: migration_cred.to_bucket, + trust_level: (level - 2).into(), + blockages: new_blockages, + }, + )) +} + +impl BridgeAuth { + /// Receive a blockage migration request + pub fn handle_blockage_migration(&mut self, req: Request) -> Result { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + if req.P_lox.is_identity() || req.P_mig.is_identity() { + return Err(ProofError::VerificationFailure); + } + + // The trust level must be at least MIN_TRUST_LEVEL + let level: u32 = match scalar_u32(&req.trust_level) { + Some(v) => v, + None => return Err(ProofError::VerificationFailure), + }; + if level < MIN_TRUST_LEVEL { + return Err(ProofError::VerificationFailure); + } + + // Recompute the "error factors" using knowledge of our own + // (the issuer's) private key instead of knowledge of the + // hidden attributes + let Vprime_lox = (self.lox_priv.x[0] + + self.lox_priv.x[1] * req.id + + self.lox_priv.x[3] * req.trust_level) + * req.P_lox + + self.lox_priv.x[2] * req.CBucket + + self.lox_priv.x[4] * req.CSince + + self.lox_priv.x[5] * req.CInvRemain + + self.lox_priv.x[6] * req.CBlockages + - req.CQ_lox; + + let migration_type: Scalar = MigrationType::Blockage.into(); + let Vprime_mig = (self.migration_priv.x[0] + + self.migration_priv.x[1] * req.id + + self.migration_priv.x[4] * migration_type) + * req.P_mig + + self.migration_priv.x[2] * req.CFromBucket + + self.migration_priv.x[3] * req.CToBucket + - req.CQ_mig; + + // Verify the ZKP + let mut transcript = Transcript::new(b"blockage migration request"); + requestproof::verify_compact( + &req.piUser, + &mut transcript, + requestproof::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P_lox: &req.P_lox.compress(), + CBucket: &req.CBucket.compress(), + CSince: &req.CSince.compress(), + CInvRemain: &req.CInvRemain.compress(), + CBlockages: &req.CBlockages.compress(), + V_lox: &Vprime_lox.compress(), + Xbucket: &self.lox_pub.X[2].compress(), + Xsince: &self.lox_pub.X[4].compress(), + Xinvremain: &self.lox_pub.X[5].compress(), + Xblockages: &self.lox_pub.X[6].compress(), + P_mig: &req.P_mig.compress(), + CFromBucket: &req.CFromBucket.compress(), + CToBucket: &req.CToBucket.compress(), + V_mig: &Vprime_mig.compress(), + Xfrombucket: &self.migration_pub.X[2].compress(), + Xtobucket: &self.migration_pub.X[3].compress(), + D: &req.D.compress(), + EncIdClient0: &req.EncIdClient.0.compress(), + EncIdClient1: &req.EncIdClient.1.compress(), + EncBucket0: &req.EncBucket.0.compress(), + EncBucket1: &req.EncBucket.1.compress(), + EncBlockages0: &req.EncBlockages.0.compress(), + EncBlockages1_minus_B: &(req.EncBlockages.1 - B).compress(), + }, + )?; + + // Ensure the id has not been seen before, and add it to the + // seen list. + if self.id_filter.filter(&req.id) == SeenType::Seen { + return Err(ProofError::VerificationFailure); + } + + // Blind issuing of the new Lox credential + + // Choose a random server id component to add to the client's + // (blinded) id component + let mut rng = rand::thread_rng(); + let id_server = Scalar::random(&mut rng); + let EncId = (req.EncIdClient.0, req.EncIdClient.1 + &id_server * Btable); + + // Create the trust_level attrubute (Scalar), which will be + // 2 levels down from the one in the provided credential + let trust_level: Scalar = (level - 2).into(); + + // Create the level_since attribute (Scalar), which is today's + // Julian date + let level_since: Scalar = self.today().into(); + + // The invites remaining is the appropriate number for the new + // level (note that LEVEL_INVITATIONS[i] is the number of + // invitations for moving from level i to level i+1) + let invremain: Scalar = LEVEL_INVITATIONS[(level - 3) as usize].into(); + + // Because of the bug in the zkp crate, encrypt the invites + // remaining instead of sending it in the clear + let sinvremain = Scalar::random(&mut rng); + let EncInvRemain = ( + &sinvremain * Btable, + &invremain * Btable + sinvremain * req.D, + ); + + // Compute the MAC on the visible attributes + let b = Scalar::random(&mut rng); + let P = &b * Btable; + let QHc = (self.lox_priv.x[0] + + self.lox_priv.x[3] * trust_level + + self.lox_priv.x[4] * level_since) + * P; + + // El Gamal encrypt it to the public key req.D + let s = Scalar::random(&mut rng); + let EncQHc = (&s * Btable, QHc + s * req.D); + + // Homomorphically compute the part of the MAC corresponding to + // the blinded attributes + let tid = self.lox_priv.x[1] * b; + let TId = &tid * Atable; + let EncQId = (tid * EncId.0, tid * EncId.1); + let tbucket = self.lox_priv.x[2] * b; + let TBucket = &tbucket * Atable; + let EncQBucket = (tbucket * req.EncBucket.0, tbucket * req.EncBucket.1); + let tinvremain = self.lox_priv.x[5] * b; + let TInvRemain = &tinvremain * Atable; + let EncQInvRemain = (tinvremain * EncInvRemain.0, tinvremain * EncInvRemain.1); + let tblockages = self.lox_priv.x[6] * b; + let TBlockages = &tblockages * Atable; + let EncQBlockages = ( + tblockages * req.EncBlockages.0, + tblockages * req.EncBlockages.1, + ); + + let EncQ = ( + EncQHc.0 + EncQId.0 + EncQBucket.0 + EncQInvRemain.0 + EncQBlockages.0, + EncQHc.1 + EncQId.1 + EncQBucket.1 + EncQInvRemain.1 + EncQBlockages.1, + ); + + let mut transcript = Transcript::new(b"blockage migration issuing"); + let piBlindIssue = blindissue::prove_compact( + &mut transcript, + blindissue::ProveAssignments { + A: &A, + B: &B, + P: &P, + EncQ0: &EncQ.0, + EncQ1: &EncQ.1, + X0: &self.lox_pub.X[0], + Xid: &self.lox_pub.X[1], + Xbucket: &self.lox_pub.X[2], + Xlevel: &self.lox_pub.X[3], + Xsince: &self.lox_pub.X[4], + Xinvremain: &self.lox_pub.X[5], + Xblockages: &self.lox_pub.X[6], + Plevel: &(trust_level * P), + Psince: &(level_since * P), + TId: &TId, + TBucket: &TBucket, + TInvRemain: &TInvRemain, + TBlockages: &TBlockages, + D: &req.D, + EncId0: &EncId.0, + EncId1: &EncId.1, + EncBucket0: &req.EncBucket.0, + EncBucket1: &req.EncBucket.1, + EncInvRemain0: &EncInvRemain.0, + EncInvRemain1: &EncInvRemain.1, + EncBlockages0: &req.EncBlockages.0, + EncBlockages1: &req.EncBlockages.1, + x0: &self.lox_priv.x[0], + x0tilde: &self.lox_priv.x0tilde, + xid: &self.lox_priv.x[1], + xbucket: &self.lox_priv.x[2], + xlevel: &self.lox_priv.x[3], + xsince: &self.lox_priv.x[4], + xinvremain: &self.lox_priv.x[5], + xblockages: &self.lox_priv.x[6], + s: &s, + b: &b, + tid: &tid, + tbucket: &tbucket, + tinvremain: &tinvremain, + tblockages: &tblockages, + }, + ) + .0; + + Ok(Response { + level_since, + P, + EncQ, + EncInvRemain, + id_server, + TId, + TBucket, + TInvRemain, + TBlockages, + piBlindIssue, + }) + } +} + +/// Handle the response to the request, producing the new Lox credential +/// if successful. +pub fn handle_response( + state: State, + resp: Response, + lox_pub: &IssuerPubKey, +) -> Result { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + if resp.P.is_identity() { + return Err(ProofError::VerificationFailure); + } + + // Add the server's contribution to the id to our own, both in plain + // and encrypted form + let id = state.id_client + resp.id_server; + let EncId = ( + state.EncIdClient.0, + state.EncIdClient.1 + &resp.id_server * Btable, + ); + + let new_level: u32 = match scalar_u32(&state.trust_level) { + Some(v) => v, + None => return Err(ProofError::VerificationFailure), + }; + if new_level < 1 { + return Err(ProofError::VerificationFailure); + } + + // The invites remaining is the appropriate number for the new level + // (note that LEVEL_INVITATIONS[i] is the number of invitations for + // moving from level i to level i+1) + let invremain: Scalar = LEVEL_INVITATIONS[(new_level - 1) as usize].into(); + + // Decrypt EncInvRemain + let recv_invremain = resp.EncInvRemain.1 - (state.d * resp.EncInvRemain.0); + + if recv_invremain != &invremain * Btable { + return Err(ProofError::VerificationFailure); + } + + // Verify the proof + let mut transcript = Transcript::new(b"blockage migration issuing"); + blindissue::verify_compact( + &resp.piBlindIssue, + &mut transcript, + blindissue::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P: &resp.P.compress(), + EncQ0: &resp.EncQ.0.compress(), + EncQ1: &resp.EncQ.1.compress(), + X0: &lox_pub.X[0].compress(), + Xid: &lox_pub.X[1].compress(), + Xbucket: &lox_pub.X[2].compress(), + Xlevel: &lox_pub.X[3].compress(), + Xsince: &lox_pub.X[4].compress(), + Xinvremain: &lox_pub.X[5].compress(), + Xblockages: &lox_pub.X[6].compress(), + Plevel: &(state.trust_level * resp.P).compress(), + Psince: &(resp.level_since * resp.P).compress(), + TId: &resp.TId.compress(), + TBucket: &resp.TBucket.compress(), + TInvRemain: &resp.TInvRemain.compress(), + TBlockages: &resp.TBlockages.compress(), + D: &state.D.compress(), + EncId0: &EncId.0.compress(), + EncId1: &EncId.1.compress(), + EncBucket0: &state.EncBucket.0.compress(), + EncBucket1: &state.EncBucket.1.compress(), + EncInvRemain0: &resp.EncInvRemain.0.compress(), + EncInvRemain1: &resp.EncInvRemain.1.compress(), + EncBlockages0: &state.EncBlockages.0.compress(), + EncBlockages1: &state.EncBlockages.1.compress(), + }, + )?; + + // Decrypt EncQ + let Q = resp.EncQ.1 - (state.d * resp.EncQ.0); + + Ok(cred::Lox { + P: resp.P, + Q, + id, + bucket: state.to_bucket, + trust_level: new_level.into(), + level_since: resp.level_since, + invites_remaining: invremain, + blockages: state.blockages, + }) +} diff --git a/crates/lox-library/src/proto/migration.rs b/crates/lox-library/src/proto/migration.rs index 8af5672..27cb622 100644 --- a/crates/lox-library/src/proto/migration.rs +++ b/crates/lox-library/src/proto/migration.rs @@ -1,9 +1,8 @@ /*! A module for the protocol for the user to migrate from one bucket to -another (and possibly also change trust level). +another and change trust level from untrusted (trust level 0) to trusted +(trust level 1). -For the case of migrating from trust level 0 (a one-bridge bucket) to -trust level 1 (a three-bridge bucket), the user presents their current -Lox credential: +The user presents their current Lox credential: - id: revealed - bucket: blinded @@ -163,8 +162,8 @@ pub fn request( return Err(ProofError::VerificationFailure); } - // We only support migrating from trust level 0 to trust level 1 - // right now + // This protocol only allows migrating from trust level 0 to trust + // level 1 if lox_cred.trust_level != Scalar::zero() { return Err(ProofError::VerificationFailure); } diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 00e1987..af7ddcd 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -126,6 +126,14 @@ impl TestHarness { let resp = self.ba.handle_check_blockage(req).unwrap(); check_blockage::handle_response(state, resp).unwrap() } + + fn blockage_migration(&mut self, cred: &cred::Lox, mig: &cred::Migration) -> cred::Lox { + let (req, state) = + blockage_migration::request(&cred, &mig, &self.ba.lox_pub, &self.ba.migration_pub) + .unwrap(); + let resp = self.ba.handle_blockage_migration(req).unwrap(); + blockage_migration::handle_response(state, resp, &self.ba.lox_pub).unwrap() + } } #[test] @@ -358,7 +366,7 @@ fn test_mark_unreachable() { } #[test] -fn test_check_blockage() { +fn test_blockage_migration() { let mut th = TestHarness::new(); // Join an untrusted user @@ -420,4 +428,10 @@ fn test_check_blockage() { let migration = th.check_blockage(&cred3); println!("migration = {:?}", migration); + + // Migrate + let cred4 = th.blockage_migration(&cred3, &migration); + + println!("cred4 = {:?}", cred4); + assert!(th.ba.verify_lox(&cred4)); } From a56ac8786882c9625bff2efbf05051429ff58844 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Sat, 5 Jun 2021 13:36:09 -0400 Subject: [PATCH 048/115] Change IssuerPubKey constructor to be more functional --- crates/lox-library/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 253313a..c74686c 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -95,9 +95,8 @@ impl IssuerPubKey { X.push(&privkey.x0tilde * Atable + &privkey.x[0] * Btable); // The other elements (1 through n) are X[i] = x[i]*A - for i in 1..n_plus_one { - X.push(&privkey.x[i] * Atable); - } + X.extend(privkey.x.iter().skip(1).map(|xi| xi * Atable)); + IssuerPubKey { X } } } From c73230e9376b7ddf1d06e73b6bf0f5e100f9258b Mon Sep 17 00:00:00 2001 From: onyinyang Date: Tue, 18 May 2021 12:04:21 -0400 Subject: [PATCH 049/115] Added Bridgeline to open-entry --- crates/lox-library/src/proto/open_invite.rs | 14 ++++++++++---- crates/lox-library/src/tests.rs | 16 ++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/crates/lox-library/src/proto/open_invite.rs b/crates/lox-library/src/proto/open_invite.rs index 3d7b20c..a818376 100644 --- a/crates/lox-library/src/proto/open_invite.rs +++ b/crates/lox-library/src/proto/open_invite.rs @@ -22,7 +22,7 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; -use super::super::bridge_table; +use super::super::{{bridge_table, BridgeLine}}; use super::super::cred; use super::super::dup_filter::SeenType; use super::super::OPENINV_LENGTH; @@ -55,6 +55,7 @@ pub struct Response { bucket: Scalar, level_since: Scalar, piBlindIssue: CompactProof, + bridge_line: BridgeLine, } // The userblinding ZKP @@ -189,6 +190,8 @@ impl BridgeAuth { // of the bucket id (u32) and the bucket's decryption key ([u8; 16]) let bucket_key = self.bridge_table.keys[bucket_id]; let bucket: Scalar = bridge_table::to_scalar(bucket_id_u32, &bucket_key); + let pre_line = self.bridge_table.decrypt_bucket_id(bucket_id_u32, &bucket_key).unwrap().0; + let bridge_line: BridgeLine = pre_line[0]; // Create the level_since attribute (Scalar), which is today's // Julian date @@ -253,6 +256,7 @@ impl BridgeAuth { bucket, level_since, piBlindIssue, + bridge_line, }) } } @@ -263,7 +267,7 @@ pub fn handle_response( state: State, resp: Response, lox_pub: &IssuerPubKey, -) -> Result { +) -> Result<(cred::Lox, bridge_table::BridgeLine), ProofError> { let A: &RistrettoPoint = &CMZ_A; let B: &RistrettoPoint = &CMZ_B; let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; @@ -307,7 +311,7 @@ pub fn handle_response( // Decrypt EncQ let Q = resp.EncQ.1 - (state.d * resp.EncQ.0); - Ok(cred::Lox { + Ok((cred::Lox { P: resp.P, Q, id, @@ -316,5 +320,7 @@ pub fn handle_response( level_since: resp.level_since, invites_remaining: Scalar::zero(), blockages: Scalar::zero(), - }) + }, + resp.bridge_line, + )) } diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index af7ddcd..e681d5e 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -45,7 +45,7 @@ impl TestHarness { self.ba.advance_days(days); } - fn open_invite(&mut self) -> cred::Lox { + fn open_invite(&mut self) -> (cred::Lox, bridge_table::BridgeLine) { // Issue an open invitation let inv = self.bdb.invite(); @@ -141,7 +141,7 @@ fn test_open_invite() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite(); + let cred = th.open_invite().0; // Check that we can use the credential to read a bucket let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); @@ -158,7 +158,7 @@ fn test_open_invite() { fn test_trust_promotion() { let mut th = TestHarness::new(); - let cred = th.open_invite(); + let cred = th.open_invite().0; assert!(th.ba.verify_lox(&cred)); // Time passes @@ -181,7 +181,7 @@ fn test_trust_promotion() { fn test_level0_migration() { let mut th = TestHarness::new(); - let cred = th.open_invite(); + let cred = th.open_invite().0; assert!(th.ba.verify_lox(&cred)); // Time passes @@ -208,7 +208,7 @@ fn test_level_up() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite(); + let cred = th.open_invite().0; // Time passes th.advance_days(47); @@ -248,7 +248,7 @@ fn test_issue_invite() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite(); + let cred = th.open_invite().0; // Time passes th.advance_days(47); @@ -280,7 +280,7 @@ fn test_redeem_invite() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite(); + let cred = th.open_invite().0; // Time passes th.advance_days(47); @@ -370,7 +370,7 @@ fn test_blockage_migration() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite(); + let cred = th.open_invite().0; // Time passes th.advance_days(47); From fd05dce77ddd7fab43e3b245dd547769e0579cf2 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Tue, 18 May 2021 14:46:35 -0400 Subject: [PATCH 050/115] Fixed comments from code review --- crates/lox-library/src/proto/open_invite.rs | 31 +++++++++++---------- crates/lox-library/src/tests.rs | 4 ++- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/crates/lox-library/src/proto/open_invite.rs b/crates/lox-library/src/proto/open_invite.rs index a818376..45ce347 100644 --- a/crates/lox-library/src/proto/open_invite.rs +++ b/crates/lox-library/src/proto/open_invite.rs @@ -22,7 +22,8 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; -use super::super::{{bridge_table, BridgeLine}}; +use super::super::bridge_table; +use super::super::bridge_table::BridgeLine; use super::super::cred; use super::super::dup_filter::SeenType; use super::super::OPENINV_LENGTH; @@ -190,8 +191,7 @@ impl BridgeAuth { // of the bucket id (u32) and the bucket's decryption key ([u8; 16]) let bucket_key = self.bridge_table.keys[bucket_id]; let bucket: Scalar = bridge_table::to_scalar(bucket_id_u32, &bucket_key); - let pre_line = self.bridge_table.decrypt_bucket_id(bucket_id_u32, &bucket_key).unwrap().0; - let bridge_line: BridgeLine = pre_line[0]; + let bridge_line = self.bridge_table.buckets[bucket_id][0]; // Create the level_since attribute (Scalar), which is today's // Julian date @@ -267,7 +267,7 @@ pub fn handle_response( state: State, resp: Response, lox_pub: &IssuerPubKey, -) -> Result<(cred::Lox, bridge_table::BridgeLine), ProofError> { +) -> Result<(cred::Lox, BridgeLine), ProofError> { let A: &RistrettoPoint = &CMZ_A; let B: &RistrettoPoint = &CMZ_B; let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; @@ -311,16 +311,17 @@ pub fn handle_response( // Decrypt EncQ let Q = resp.EncQ.1 - (state.d * resp.EncQ.0); - Ok((cred::Lox { - P: resp.P, - Q, - id, - bucket: resp.bucket, - trust_level: Scalar::zero(), - level_since: resp.level_since, - invites_remaining: Scalar::zero(), - blockages: Scalar::zero(), - }, - resp.bridge_line, + Ok(( + cred::Lox { + P: resp.P, + Q, + id, + bucket: resp.bucket, + trust_level: Scalar::zero(), + level_since: resp.level_since, + invites_remaining: Scalar::zero(), + blockages: Scalar::zero(), + }, + resp.bridge_line, )) } diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index e681d5e..d2861b8 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -141,7 +141,7 @@ fn test_open_invite() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite().0; + let (cred, bridgeline) = th.open_invite(); // Check that we can use the credential to read a bucket let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); @@ -150,8 +150,10 @@ fn test_open_invite() { bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); println!("cred = {:?}", cred); println!("bucket = {:?}", bucket); + println!("bridgeline = {:?}", bridgeline); assert!(bucket.1.is_none()); assert!(th.ba.verify_lox(&cred)); + assert!(bridgeline == bucket.0[0]); } #[test] From 179fea5e23b18908ce4483514bd37a975bfa0848 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 26 May 2021 13:16:14 -0400 Subject: [PATCH 051/115] Added serialization and deserialization for all but check blockage and trust promotion --- crates/lox-library/Cargo.toml | 2 ++ crates/lox-library/src/bridge_table.rs | 10 +++++++++- crates/lox-library/src/proto/blockage_migration.rs | 5 +++++ crates/lox-library/src/proto/issue_invite.rs | 4 ++++ crates/lox-library/src/proto/level_up.rs | 4 ++++ crates/lox-library/src/proto/migration.rs | 4 ++++ crates/lox-library/src/proto/open_invite.rs | 10 +++++++++- crates/lox-library/src/proto/redeem_invite.rs | 4 ++++ 8 files changed, 41 insertions(+), 2 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index ea88540..0adbd53 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -12,6 +12,8 @@ zkp = "0.8" bincode = "1" rand = "0.7" serde = "1" +serde-big-array = "0.3.2" +serde_with = "1.9.1" sha2 = "0.9" lazy_static = "1" hex_fmt = "0.3" diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index 929ee64..94c9a46 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -18,10 +18,17 @@ use curve25519_dalek::ristretto::CompressedRistretto; use curve25519_dalek::ristretto::RistrettoBasepointTable; use curve25519_dalek::scalar::Scalar; use rand::RngCore; +use serde::{Serialize, Deserialize}; +use serde_big_array::big_array; use std::collections::{HashMap, HashSet}; use std::convert::TryInto; use subtle::ConstantTimeEq; +big_array! { + BigArray; + +202, +} + /// Each bridge information line is serialized into this many bytes pub const BRIDGE_BYTES: usize = 220; @@ -35,7 +42,7 @@ pub const MAX_BRIDGES_PER_BUCKET: usize = 3; pub const MIN_BUCKET_REACHABILITY: usize = 2; /// A bridge information line -#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] +#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)] pub struct BridgeLine { /// IPv4 or IPv6 address pub addr: [u8; 16], @@ -43,6 +50,7 @@ pub struct BridgeLine { pub port: u16, /// other protocol information, including pluggable transport, /// public key, etc. + #[serde(with = "BigArray")] pub info: [u8; BRIDGE_BYTES - 18], } diff --git a/crates/lox-library/src/proto/blockage_migration.rs b/crates/lox-library/src/proto/blockage_migration.rs index 694ad4e..8a1aab6 100644 --- a/crates/lox-library/src/proto/blockage_migration.rs +++ b/crates/lox-library/src/proto/blockage_migration.rs @@ -43,6 +43,8 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; +use serde::{Serialize, Deserialize}; + use super::super::cred; use super::super::dup_filter::SeenType; use super::super::migration_table::MigrationType; @@ -52,6 +54,7 @@ use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; use super::check_blockage::MIN_TRUST_LEVEL; use super::level_up::LEVEL_INVITATIONS; +#[derive(Serialize, Deserialize)] pub struct Request { // Fields for blind showing the Lox credential P_lox: RistrettoPoint, @@ -92,6 +95,8 @@ pub struct State { blockages: Scalar, } + +#[derive(Serialize, Deserialize)] pub struct Response { // The new attributes; the trust_level and invites_remaining are // implicit diff --git a/crates/lox-library/src/proto/issue_invite.rs b/crates/lox-library/src/proto/issue_invite.rs index 699b660..97446f3 100644 --- a/crates/lox-library/src/proto/issue_invite.rs +++ b/crates/lox-library/src/proto/issue_invite.rs @@ -54,12 +54,15 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; +use serde::{Serialize, Deserialize}; + use super::super::cred; use super::super::dup_filter::SeenType; use super::super::scalar_u32; use super::super::{BridgeAuth, IssuerPubKey}; use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; +#[derive(Serialize, Deserialize)] pub struct Request { // Fields for blind showing the Lox credential P: RistrettoPoint, @@ -116,6 +119,7 @@ pub struct State { inv_id_client: Scalar, } +#[derive(Serialize, Deserialize)] pub struct Response { // The fields for the new Lox credential; the new invites_remaining // is one less than the old value, so we don't have to include it diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs index 553cdcf..aa23249 100644 --- a/crates/lox-library/src/proto/level_up.rs +++ b/crates/lox-library/src/proto/level_up.rs @@ -47,6 +47,8 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; +use serde::{Serialize, Deserialize}; + use super::super::cred; use super::super::dup_filter::SeenType; use super::super::{pt_dbl, scalar_dbl, scalar_u32}; @@ -80,6 +82,7 @@ pub const LEVEL_INVITATIONS: [u32; MAX_LEVEL + 1] = [0, 2, 4, 6, 8]; // one or more bits to the ZKP. pub const MAX_BLOCKAGES: [u32; MAX_LEVEL + 1] = [0, 4, 3, 2, 2]; +#[derive(Serialize, Deserialize)] pub struct Request { // Fields for blind showing the Lox credential P: RistrettoPoint, @@ -148,6 +151,7 @@ pub struct State { blockages: Scalar, } +#[derive(Serialize, Deserialize)] pub struct Response { // The fields for the new Lox credential; the new trust level is one // more than the old trust level, so we don't have to include it diff --git a/crates/lox-library/src/proto/migration.rs b/crates/lox-library/src/proto/migration.rs index 27cb622..bce93fb 100644 --- a/crates/lox-library/src/proto/migration.rs +++ b/crates/lox-library/src/proto/migration.rs @@ -39,11 +39,14 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; +use serde::{Serialize, Deserialize}; + use super::super::cred; use super::super::dup_filter::SeenType; use super::super::{BridgeAuth, IssuerPubKey}; use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; +#[derive(Serialize, Deserialize)] pub struct Request { // Fields for blind showing the Lox credential // We don't need to include invites_remaining or blockages, @@ -80,6 +83,7 @@ pub struct State { to_bucket: Scalar, } +#[derive(Serialize, Deserialize)] pub struct Response { // The new attributes; trust_level = 1 is implicit level_since: Scalar, diff --git a/crates/lox-library/src/proto/open_invite.rs b/crates/lox-library/src/proto/open_invite.rs index 45ce347..fb9e86d 100644 --- a/crates/lox-library/src/proto/open_invite.rs +++ b/crates/lox-library/src/proto/open_invite.rs @@ -22,6 +22,9 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; +use serde::{Serialize, Deserialize}; +use serde_big_array::big_array; + use super::super::bridge_table; use super::super::bridge_table::BridgeLine; use super::super::cred; @@ -30,16 +33,20 @@ use super::super::OPENINV_LENGTH; use super::super::{BridgeAuth, BridgeDb, IssuerPubKey}; use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; +big_array! { BigArray; } + /// The request message for this protocol +#[derive(Serialize, Deserialize)] pub struct Request { + #[serde(with = "BigArray")] invite: [u8; OPENINV_LENGTH], D: RistrettoPoint, EncIdClient: (RistrettoPoint, RistrettoPoint), piUserBlinding: CompactProof, } -#[derive(Debug)] /// The client state for this protocol +#[derive(Debug)] pub struct State { d: Scalar, D: RistrettoPoint, @@ -48,6 +55,7 @@ pub struct State { } /// The response message for this protocol +#[derive(Serialize, Deserialize)] pub struct Response { P: RistrettoPoint, EncQ: (RistrettoPoint, RistrettoPoint), diff --git a/crates/lox-library/src/proto/redeem_invite.rs b/crates/lox-library/src/proto/redeem_invite.rs index 20570e3..ed285e9 100644 --- a/crates/lox-library/src/proto/redeem_invite.rs +++ b/crates/lox-library/src/proto/redeem_invite.rs @@ -30,6 +30,8 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; +use serde::{Serialize, Deserialize}; + use super::super::cred; use super::super::dup_filter::SeenType; use super::super::{pt_dbl, scalar_dbl, scalar_u32}; @@ -41,6 +43,7 @@ use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; /// also add bits to the zero knowledge proof. pub const INVITATION_EXPIRY: u32 = 15; +#[derive(Serialize, Deserialize)] pub struct Request { // Fields for showing the Invitation credential P: RistrettoPoint, @@ -82,6 +85,7 @@ pub struct State { blockages: Scalar, } +#[derive(Serialize, Deserialize)] pub struct Response { // The fields for the new Lox credential; the new trust level is 1 // and the new invites_remaining is 0, so we don't have to include From f6ffdd77bb95390e5c55a49f3251ce0a86d1946d Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 26 May 2021 17:29:53 -0400 Subject: [PATCH 052/115] Added serialization/deserialization for check_blockage and trust_promotion --- crates/lox-library/src/proto/check_blockage.rs | 8 +++++++- crates/lox-library/src/proto/trust_promotion.rs | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/crates/lox-library/src/proto/check_blockage.rs b/crates/lox-library/src/proto/check_blockage.rs index a60958c..a879aa3 100644 --- a/crates/lox-library/src/proto/check_blockage.rs +++ b/crates/lox-library/src/proto/check_blockage.rs @@ -37,6 +37,9 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; +use serde::{Serialize,Deserialize}; +use serde_with::serde_as; + use std::collections::HashMap; use super::super::cred; @@ -50,6 +53,7 @@ use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; /// perform this protocol. pub const MIN_TRUST_LEVEL: u32 = 3; +#[derive(Serialize, Deserialize)] pub struct Request { // Fields for blind showing the Lox credential P: RistrettoPoint, @@ -78,7 +82,8 @@ pub struct State { bucket: Scalar, } -#[derive(Debug)] +#[serde_as] +#[derive(Serialize, Deserialize, Debug)] pub struct Response { // The encrypted MAC for the Migration Key credential Pk: RistrettoPoint, @@ -87,6 +92,7 @@ pub struct Response { // A table of encrypted Migration credentials; the encryption keys // are formed from the possible values of Qk (the decrypted form of // EncQk) + #[serde_as(as = "Vec<(_,[_; migration_table::ENC_MIGRATION_BYTES])>")] enc_migration_table: HashMap<[u8; 16], [u8; migration_table::ENC_MIGRATION_BYTES]>, } diff --git a/crates/lox-library/src/proto/trust_promotion.rs b/crates/lox-library/src/proto/trust_promotion.rs index bced670..a49a77b 100644 --- a/crates/lox-library/src/proto/trust_promotion.rs +++ b/crates/lox-library/src/proto/trust_promotion.rs @@ -36,6 +36,9 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; +use serde::{Serialize, Deserialize}; +use serde_with::serde_as; + use std::collections::HashMap; use super::super::cred; @@ -54,6 +57,7 @@ use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; /// with the system in order to move up trust levels. pub const UNTRUSTED_INTERVAL: u32 = 30; +#[derive(Serialize, Deserialize)] pub struct Request { // Fields for blind showing the Lox credential // We don't need to include trust_level, invites_remaining, or @@ -101,7 +105,8 @@ pub struct State { bucket: Scalar, } -#[derive(Debug)] +#[serde_as] +#[derive(Serialize, Deserialize, Debug)] pub struct Response { // The encrypted MAC for the Migration Key credential Pk: RistrettoPoint, @@ -110,6 +115,7 @@ pub struct Response { // A table of encrypted Migration credentials; the encryption keys // are formed from the possible values of Qk (the decrypted form of // EncQk) + #[serde_as(as = "Vec<(_,[_; migration_table::ENC_MIGRATION_BYTES])>")] enc_migration_table: HashMap<[u8; 16], [u8; migration_table::ENC_MIGRATION_BYTES]>, } From d9d349d0f75526286a93db9d5dcc3f138bf3acf9 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 26 May 2021 18:15:13 -0400 Subject: [PATCH 053/115] Replace big_array with serde_as, cargo fmt likes things to be alphabetical --- crates/lox-library/Cargo.toml | 1 - crates/lox-library/src/bridge_table.rs | 12 ++++-------- crates/lox-library/src/proto/blockage_migration.rs | 3 +-- crates/lox-library/src/proto/check_blockage.rs | 4 ++-- crates/lox-library/src/proto/issue_invite.rs | 2 +- crates/lox-library/src/proto/level_up.rs | 2 +- crates/lox-library/src/proto/migration.rs | 2 +- crates/lox-library/src/proto/open_invite.rs | 9 ++++----- crates/lox-library/src/proto/redeem_invite.rs | 2 +- crates/lox-library/src/proto/trust_promotion.rs | 2 +- 10 files changed, 16 insertions(+), 23 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index 0adbd53..4142439 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -12,7 +12,6 @@ zkp = "0.8" bincode = "1" rand = "0.7" serde = "1" -serde-big-array = "0.3.2" serde_with = "1.9.1" sha2 = "0.9" lazy_static = "1" diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index 94c9a46..d7ef7fa 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -18,17 +18,12 @@ use curve25519_dalek::ristretto::CompressedRistretto; use curve25519_dalek::ristretto::RistrettoBasepointTable; use curve25519_dalek::scalar::Scalar; use rand::RngCore; -use serde::{Serialize, Deserialize}; -use serde_big_array::big_array; +use serde::{Deserialize, Serialize}; +use serde_with::serde_as; use std::collections::{HashMap, HashSet}; use std::convert::TryInto; use subtle::ConstantTimeEq; -big_array! { - BigArray; - +202, -} - /// Each bridge information line is serialized into this many bytes pub const BRIDGE_BYTES: usize = 220; @@ -42,6 +37,7 @@ pub const MAX_BRIDGES_PER_BUCKET: usize = 3; pub const MIN_BUCKET_REACHABILITY: usize = 2; /// A bridge information line +#[serde_as] #[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)] pub struct BridgeLine { /// IPv4 or IPv6 address @@ -50,7 +46,7 @@ pub struct BridgeLine { pub port: u16, /// other protocol information, including pluggable transport, /// public key, etc. - #[serde(with = "BigArray")] + #[serde_as(as = "[_; BRIDGE_BYTES - 18]")] pub info: [u8; BRIDGE_BYTES - 18], } diff --git a/crates/lox-library/src/proto/blockage_migration.rs b/crates/lox-library/src/proto/blockage_migration.rs index 8a1aab6..dc8c5b6 100644 --- a/crates/lox-library/src/proto/blockage_migration.rs +++ b/crates/lox-library/src/proto/blockage_migration.rs @@ -43,7 +43,7 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use super::super::cred; use super::super::dup_filter::SeenType; @@ -95,7 +95,6 @@ pub struct State { blockages: Scalar, } - #[derive(Serialize, Deserialize)] pub struct Response { // The new attributes; the trust_level and invites_remaining are diff --git a/crates/lox-library/src/proto/check_blockage.rs b/crates/lox-library/src/proto/check_blockage.rs index a879aa3..9cba4fc 100644 --- a/crates/lox-library/src/proto/check_blockage.rs +++ b/crates/lox-library/src/proto/check_blockage.rs @@ -37,7 +37,7 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; -use serde::{Serialize,Deserialize}; +use serde::{Deserialize, Serialize}; use serde_with::serde_as; use std::collections::HashMap; @@ -92,7 +92,7 @@ pub struct Response { // A table of encrypted Migration credentials; the encryption keys // are formed from the possible values of Qk (the decrypted form of // EncQk) - #[serde_as(as = "Vec<(_,[_; migration_table::ENC_MIGRATION_BYTES])>")] + #[serde_as(as = "Vec<(_,[_; migration_table::ENC_MIGRATION_BYTES])>")] enc_migration_table: HashMap<[u8; 16], [u8; migration_table::ENC_MIGRATION_BYTES]>, } diff --git a/crates/lox-library/src/proto/issue_invite.rs b/crates/lox-library/src/proto/issue_invite.rs index 97446f3..f2ed162 100644 --- a/crates/lox-library/src/proto/issue_invite.rs +++ b/crates/lox-library/src/proto/issue_invite.rs @@ -54,7 +54,7 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use super::super::cred; use super::super::dup_filter::SeenType; diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs index aa23249..7978e68 100644 --- a/crates/lox-library/src/proto/level_up.rs +++ b/crates/lox-library/src/proto/level_up.rs @@ -47,7 +47,7 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use super::super::cred; use super::super::dup_filter::SeenType; diff --git a/crates/lox-library/src/proto/migration.rs b/crates/lox-library/src/proto/migration.rs index bce93fb..383dfa2 100644 --- a/crates/lox-library/src/proto/migration.rs +++ b/crates/lox-library/src/proto/migration.rs @@ -39,7 +39,7 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use super::super::cred; use super::super::dup_filter::SeenType; diff --git a/crates/lox-library/src/proto/open_invite.rs b/crates/lox-library/src/proto/open_invite.rs index fb9e86d..306489a 100644 --- a/crates/lox-library/src/proto/open_invite.rs +++ b/crates/lox-library/src/proto/open_invite.rs @@ -22,8 +22,8 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; -use serde::{Serialize, Deserialize}; -use serde_big_array::big_array; +use serde::{Deserialize, Serialize}; +use serde_with::serde_as; use super::super::bridge_table; use super::super::bridge_table::BridgeLine; @@ -33,12 +33,11 @@ use super::super::OPENINV_LENGTH; use super::super::{BridgeAuth, BridgeDb, IssuerPubKey}; use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE}; -big_array! { BigArray; } - /// The request message for this protocol +#[serde_as] #[derive(Serialize, Deserialize)] pub struct Request { - #[serde(with = "BigArray")] + #[serde_as(as = "[_; OPENINV_LENGTH]")] invite: [u8; OPENINV_LENGTH], D: RistrettoPoint, EncIdClient: (RistrettoPoint, RistrettoPoint), diff --git a/crates/lox-library/src/proto/redeem_invite.rs b/crates/lox-library/src/proto/redeem_invite.rs index ed285e9..59ce73b 100644 --- a/crates/lox-library/src/proto/redeem_invite.rs +++ b/crates/lox-library/src/proto/redeem_invite.rs @@ -30,7 +30,7 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use super::super::cred; use super::super::dup_filter::SeenType; diff --git a/crates/lox-library/src/proto/trust_promotion.rs b/crates/lox-library/src/proto/trust_promotion.rs index a49a77b..fed5a25 100644 --- a/crates/lox-library/src/proto/trust_promotion.rs +++ b/crates/lox-library/src/proto/trust_promotion.rs @@ -36,7 +36,7 @@ use zkp::CompactProof; use zkp::ProofError; use zkp::Transcript; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use serde_with::serde_as; use std::collections::HashMap; From 8496c63b14bffe2ad0fe6927756539ad66cd7458 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Tue, 1 Jun 2021 15:07:28 -0400 Subject: [PATCH 054/115] Added serialized sizes for request and response in open invite --- crates/lox-library/src/tests.rs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index d2861b8..c10973d 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -45,14 +45,25 @@ impl TestHarness { self.ba.advance_days(days); } - fn open_invite(&mut self) -> (cred::Lox, bridge_table::BridgeLine) { + fn open_invite(&mut self) -> (usize, usize, (cred::Lox, bridge_table::BridgeLine)) { // Issue an open invitation let inv = self.bdb.invite(); // Use it to get a Lox credential let (req, state) = open_invite::request(&inv); - let resp = self.ba.handle_open_invite(req).unwrap(); - open_invite::handle_response(state, resp, &self.ba.lox_pub).unwrap() + let encoded: Vec = bincode::serialize(&req).unwrap(); + let req_len = encoded.len(); + let decoded: open_invite::Request = bincode::deserialize(&encoded[..]).unwrap(); + + let resp = self.ba.handle_open_invite(decoded).unwrap(); + let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); + let resp_len = encoded_resp.len(); + let decode_resp: open_invite::Response = bincode::deserialize(&encoded_resp[..]).unwrap(); + return ( + req_len, + resp_len, + (open_invite::handle_response(state, decode_resp, &self.ba.lox_pub).unwrap()), + ); } fn trust_promotion(&mut self, cred: &cred::Lox) -> cred::Migration { @@ -141,13 +152,15 @@ fn test_open_invite() { let mut th = TestHarness::new(); // Join an untrusted user - let (cred, bridgeline) = th.open_invite(); + let (ser_req, ser_resp, (cred, bridgeline)) = th.open_invite(); // Check that we can use the credential to read a bucket let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); let encbuckets = th.ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); + println!("Request size = {:?}", ser_req); + println!("Response size = {:?}", ser_resp); println!("cred = {:?}", cred); println!("bucket = {:?}", bucket); println!("bridgeline = {:?}", bridgeline); @@ -160,7 +173,7 @@ fn test_open_invite() { fn test_trust_promotion() { let mut th = TestHarness::new(); - let cred = th.open_invite().0; + let cred = th.open_invite().2 .0; assert!(th.ba.verify_lox(&cred)); // Time passes @@ -183,7 +196,7 @@ fn test_trust_promotion() { fn test_level0_migration() { let mut th = TestHarness::new(); - let cred = th.open_invite().0; + let cred = th.open_invite().2 .0; assert!(th.ba.verify_lox(&cred)); // Time passes @@ -210,7 +223,7 @@ fn test_level_up() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite().0; + let cred = th.open_invite().2 .0; // Time passes th.advance_days(47); @@ -250,7 +263,7 @@ fn test_issue_invite() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite().0; + let cred = th.open_invite().2 .0; // Time passes th.advance_days(47); @@ -282,7 +295,7 @@ fn test_redeem_invite() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite().0; + let cred = th.open_invite().2 .0; // Time passes th.advance_days(47); @@ -372,7 +385,7 @@ fn test_blockage_migration() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite().0; + let cred = th.open_invite().2 .0; // Time passes th.advance_days(47); From a76d3922fc6c3dff77002990ed5f21252bc67e58 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 2 Jun 2021 12:18:58 -0400 Subject: [PATCH 055/115] Added timing and perfstat struct for open invite --- crates/lox-library/src/tests.rs | 56 ++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index c10973d..551b148 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -4,6 +4,16 @@ BridgeLine::random() or private fields */ use super::bridge_table::BridgeLine; use super::proto::*; use super::*; +use std::time::{Duration, Instant}; + +struct PerfStat { + // Report performance metrics for each test + req_len: usize, + resp_len: usize, + req_t: Duration, + resp_t: Duration, + resp_handle_t: Duration, +} struct TestHarness { bdb: BridgeDb, @@ -45,24 +55,39 @@ impl TestHarness { self.ba.advance_days(days); } - fn open_invite(&mut self) -> (usize, usize, (cred::Lox, bridge_table::BridgeLine)) { + fn open_invite(&mut self) -> (PerfStat, (cred::Lox, bridge_table::BridgeLine)) { // Issue an open invitation let inv = self.bdb.invite(); + let req_start = Instant::now(); // Use it to get a Lox credential let (req, state) = open_invite::request(&inv); let encoded: Vec = bincode::serialize(&req).unwrap(); + let req_t = req_start.elapsed(); let req_len = encoded.len(); - let decoded: open_invite::Request = bincode::deserialize(&encoded[..]).unwrap(); + let resp_start = Instant::now(); + let decoded: open_invite::Request = bincode::deserialize(&encoded[..]).unwrap(); let resp = self.ba.handle_open_invite(decoded).unwrap(); let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); + let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); + + let resp_handle_start = Instant::now(); let decode_resp: open_invite::Response = bincode::deserialize(&encoded_resp[..]).unwrap(); + let (cred, bridgeline) = + open_invite::handle_response(state, decode_resp, &self.ba.lox_pub).unwrap(); + let resp_handle_t = resp_handle_start.elapsed(); + return ( - req_len, - resp_len, - (open_invite::handle_response(state, decode_resp, &self.ba.lox_pub).unwrap()), + PerfStat { + req_len, + resp_len, + req_t, + resp_t, + resp_handle_t, + }, + (cred, bridgeline), ); } @@ -152,15 +177,18 @@ fn test_open_invite() { let mut th = TestHarness::new(); // Join an untrusted user - let (ser_req, ser_resp, (cred, bridgeline)) = th.open_invite(); + let (perf_stat, (cred, bridgeline)) = th.open_invite(); // Check that we can use the credential to read a bucket let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); let encbuckets = th.ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); - println!("Request size = {:?}", ser_req); - println!("Response size = {:?}", ser_resp); + println!("Request size = {:?}", perf_stat.req_len); + println!("Request time = {:?}", perf_stat.req_t); + println!("Response size = {:?}", perf_stat.resp_len); + println!("Response time = {:?}", perf_stat.resp_t); + println!("Response handle time = {:?}", perf_stat.resp_handle_t); println!("cred = {:?}", cred); println!("bucket = {:?}", bucket); println!("bridgeline = {:?}", bridgeline); @@ -173,7 +201,7 @@ fn test_open_invite() { fn test_trust_promotion() { let mut th = TestHarness::new(); - let cred = th.open_invite().2 .0; + let cred = th.open_invite().1 .0; assert!(th.ba.verify_lox(&cred)); // Time passes @@ -196,7 +224,7 @@ fn test_trust_promotion() { fn test_level0_migration() { let mut th = TestHarness::new(); - let cred = th.open_invite().2 .0; + let cred = th.open_invite().1 .0; assert!(th.ba.verify_lox(&cred)); // Time passes @@ -223,7 +251,7 @@ fn test_level_up() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite().2 .0; + let cred = th.open_invite().1 .0; // Time passes th.advance_days(47); @@ -263,7 +291,7 @@ fn test_issue_invite() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite().2 .0; + let cred = th.open_invite().1 .0; // Time passes th.advance_days(47); @@ -295,7 +323,7 @@ fn test_redeem_invite() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite().2 .0; + let cred = th.open_invite().1 .0; // Time passes th.advance_days(47); @@ -385,7 +413,7 @@ fn test_blockage_migration() { let mut th = TestHarness::new(); // Join an untrusted user - let cred = th.open_invite().2 .0; + let cred = th.open_invite().1 .0; // Time passes th.advance_days(47); From 8a16f95263342cfb33444fe2a461448e8df971e1 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 2 Jun 2021 12:56:43 -0400 Subject: [PATCH 056/115] Removed types for deserialized objects --- crates/lox-library/src/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 551b148..4ca4913 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -67,14 +67,14 @@ impl TestHarness { let req_len = encoded.len(); let resp_start = Instant::now(); - let decoded: open_invite::Request = bincode::deserialize(&encoded[..]).unwrap(); + let decoded = bincode::deserialize(&encoded[..]).unwrap(); let resp = self.ba.handle_open_invite(decoded).unwrap(); let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); let resp_t = resp_start.elapsed(); let resp_len = encoded_resp.len(); let resp_handle_start = Instant::now(); - let decode_resp: open_invite::Response = bincode::deserialize(&encoded_resp[..]).unwrap(); + let decode_resp = bincode::deserialize(&encoded_resp[..]).unwrap(); let (cred, bridgeline) = open_invite::handle_response(state, decode_resp, &self.ba.lox_pub).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); From 727a6e11a3b4492b43d55f6bd0ae54decf64b4ab Mon Sep 17 00:00:00 2001 From: onyinyang Date: Thu, 3 Jun 2021 01:07:35 -0400 Subject: [PATCH 057/115] Added timing and measurements to all methods, TODO printout tests --- crates/lox-library/src/tests.rs | 415 ++++++++++++++++++++++++++++---- 1 file changed, 370 insertions(+), 45 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 4ca4913..32e5de6 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -91,23 +91,78 @@ impl TestHarness { ); } - fn trust_promotion(&mut self, cred: &cred::Lox) -> cred::Migration { + fn trust_promotion(&mut self, cred: &cred::Lox) -> (PerfStat, cred::Migration) { + let req_start = Instant::now(); let (promreq, promstate) = trust_promotion::request(&cred, &self.ba.lox_pub, self.ba.today()).unwrap(); - let promresp = self.ba.handle_trust_promotion(promreq).unwrap(); - trust_promotion::handle_response(promstate, promresp).unwrap() + let encoded: Vec = bincode::serialize(&promreq).unwrap(); + let req_t = req_start.elapsed(); + let req_len = encoded.len(); + + let resp_start = Instant::now(); + let decoded = bincode::deserialize(&encoded[..]).unwrap(); + let promresp = self.ba.handle_trust_promotion(decoded).unwrap(); + let encoded_resp: Vec = bincode::serialize(&promresp).unwrap(); + let resp_t = resp_start.elapsed(); + let resp_len = encoded_resp.len(); + + let resp_handle_start = Instant::now(); + let decode_resp = bincode::deserialize(&encoded_resp[..]).unwrap(); + let migcred = trust_promotion::handle_response(promstate, decode_resp).unwrap(); + let resp_handle_t = resp_handle_start.elapsed(); + + return ( + PerfStat { + req_len, + resp_len, + req_t, + resp_t, + resp_handle_t, + }, + migcred, + ); } - fn level0_migration(&mut self, loxcred: &cred::Lox, migcred: &cred::Migration) -> cred::Lox { + fn level0_migration( + &mut self, + loxcred: &cred::Lox, + migcred: &cred::Migration, + ) -> (PerfStat, cred::Lox) { + let req_start = Instant::now(); let (migreq, migstate) = migration::request(loxcred, migcred, &self.ba.lox_pub, &self.ba.migration_pub).unwrap(); - let migresp = self.ba.handle_migration(migreq).unwrap(); - migration::handle_response(migstate, migresp, &self.ba.lox_pub).unwrap() + let encoded: Vec = bincode::serialize(&migreq).unwrap(); + let req_t = req_start.elapsed(); + let req_len = encoded.len(); + + let resp_start = Instant::now(); + let decoded = bincode::deserialize(&encoded[..]).unwrap(); + let migresp = self.ba.handle_migration(decoded).unwrap(); + let encoded_resp: Vec = bincode::serialize(&migresp).unwrap(); + let resp_t = resp_start.elapsed(); + let resp_len = encoded_resp.len(); + + let resp_handle_start = Instant::now(); + let decode_resp: migration::Response = bincode::deserialize(&encoded_resp[..]).unwrap(); + let cred = migration::handle_response(migstate, decode_resp, &self.ba.lox_pub).unwrap(); + let resp_handle_t = resp_handle_start.elapsed(); + + return ( + PerfStat { + req_len, + resp_len, + req_t, + resp_t, + resp_handle_t, + }, + cred, + ); } - fn level_up(&mut self, cred: &cred::Lox) -> cred::Lox { + fn level_up(&mut self, cred: &cred::Lox) -> (PerfStat, cred::Lox) { // Read the bucket in the credential to get today's Bucket // Reachability credential + let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); let encbuckets = self.ba.enc_bridge_table(); let bucket = @@ -116,6 +171,7 @@ impl TestHarness { // Use the Bucket Reachability credential to advance to the next // level + let req_start = Instant::now(); let (req, state) = level_up::request( &cred, &reachcred, @@ -124,11 +180,35 @@ impl TestHarness { self.ba.today(), ) .unwrap(); - let resp = self.ba.handle_level_up(req).unwrap(); - level_up::handle_response(state, resp, &self.ba.lox_pub).unwrap() + let encoded: Vec = bincode::serialize(&req).unwrap(); + let req_t = req_start.elapsed(); + let req_len = encoded.len(); + + let resp_start = Instant::now(); + let decoded = bincode::deserialize(&encoded[..]).unwrap(); + let resp = self.ba.handle_level_up(decoded).unwrap(); + let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); + let resp_t = resp_start.elapsed(); + let resp_len = encoded_resp.len(); + + let resp_handle_start = Instant::now(); + let decode_resp = bincode::deserialize(&encoded_resp[..]).unwrap(); + let cred = level_up::handle_response(state, decode_resp, &self.ba.lox_pub).unwrap(); + let resp_handle_t = resp_handle_start.elapsed(); + + return ( + PerfStat { + req_len, + resp_len, + req_t, + resp_t, + resp_handle_t, + }, + cred, + ); } - fn issue_invite(&mut self, cred: &cred::Lox) -> (cred::Lox, cred::Invitation) { + fn issue_invite(&mut self, cred: &cred::Lox) -> (PerfStat, (cred::Lox, cred::Invitation)) { // Read the bucket in the credential to get today's Bucket // Reachability credential let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); @@ -137,6 +217,7 @@ impl TestHarness { bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); let reachcred = bucket.1.unwrap(); + let req_start = Instant::now(); let (req, state) = issue_invite::request( &cred, &reachcred, @@ -145,30 +226,140 @@ impl TestHarness { self.ba.today(), ) .unwrap(); - let resp = self.ba.handle_issue_invite(req).unwrap(); - issue_invite::handle_response(state, resp, &self.ba.lox_pub, &self.ba.invitation_pub) - .unwrap() + let encoded: Vec = bincode::serialize(&req).unwrap(); + let req_t = req_start.elapsed(); + let req_len = encoded.len(); + + let resp_start = Instant::now(); + let decoded = bincode::deserialize(&encoded[..]).unwrap(); + let resp = self.ba.handle_issue_invite(decoded).unwrap(); + let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); + let resp_t = resp_start.elapsed(); + let resp_len = encoded_resp.len(); + + let resp_handle_start = Instant::now(); + let decode_resp = bincode::deserialize(&encoded_resp[..]).unwrap(); + let (cred, invite) = issue_invite::handle_response( + state, + decode_resp, + &self.ba.lox_pub, + &self.ba.invitation_pub, + ) + .unwrap(); + let resp_handle_t = resp_handle_start.elapsed(); + + return ( + PerfStat { + req_len, + resp_len, + req_t, + resp_t, + resp_handle_t, + }, + (cred, invite), + ); } - fn redeem_invite(&mut self, inv: &cred::Invitation) -> cred::Lox { + fn redeem_invite(&mut self, inv: &cred::Invitation) -> (PerfStat, cred::Lox) { + let req_start = Instant::now(); let (req, state) = redeem_invite::request(&inv, &self.ba.invitation_pub, self.ba.today()).unwrap(); - let resp = self.ba.handle_redeem_invite(req).unwrap(); - redeem_invite::handle_response(state, resp, &self.ba.lox_pub).unwrap() + let encoded: Vec = bincode::serialize(&req).unwrap(); + let req_t = req_start.elapsed(); + let req_len = encoded.len(); + + let resp_start = Instant::now(); + let decoded = bincode::deserialize(&encoded[..]).unwrap(); + let resp = self.ba.handle_redeem_invite(decoded).unwrap(); + let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); + let resp_t = resp_start.elapsed(); + let resp_len = encoded_resp.len(); + + let resp_handle_start = Instant::now(); + let decode_resp = bincode::deserialize(&encoded_resp[..]).unwrap(); + let cred = redeem_invite::handle_response(state, decode_resp, &self.ba.lox_pub).unwrap(); + let resp_handle_t = resp_handle_start.elapsed(); + + return ( + PerfStat { + req_len, + resp_len, + req_t, + resp_t, + resp_handle_t, + }, + cred, + ); } - fn check_blockage(&mut self, cred: &cred::Lox) -> cred::Migration { + fn check_blockage(&mut self, cred: &cred::Lox) -> (PerfStat, cred::Migration) { + let req_start = Instant::now(); let (req, state) = check_blockage::request(&cred, &self.ba.lox_pub).unwrap(); - let resp = self.ba.handle_check_blockage(req).unwrap(); - check_blockage::handle_response(state, resp).unwrap() + let encoded: Vec = bincode::serialize(&req).unwrap(); + let req_t = req_start.elapsed(); + let req_len = encoded.len(); + + let resp_start = Instant::now(); + let decoded = bincode::deserialize(&encoded[..]).unwrap(); + let resp = self.ba.handle_check_blockage(decoded).unwrap(); + let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); + let resp_t = resp_start.elapsed(); + let resp_len = encoded_resp.len(); + + let resp_handle_start = Instant::now(); + let decode_resp = bincode::deserialize(&encoded_resp[..]).unwrap(); + let migcred = check_blockage::handle_response(state, decode_resp).unwrap(); + let resp_handle_t = resp_handle_start.elapsed(); + + return ( + PerfStat { + req_len, + resp_len, + req_t, + resp_t, + resp_handle_t, + }, + migcred, + ); } - fn blockage_migration(&mut self, cred: &cred::Lox, mig: &cred::Migration) -> cred::Lox { + fn blockage_migration( + &mut self, + cred: &cred::Lox, + mig: &cred::Migration, + ) -> (PerfStat, cred::Lox) { + let req_start = Instant::now(); let (req, state) = blockage_migration::request(&cred, &mig, &self.ba.lox_pub, &self.ba.migration_pub) .unwrap(); - let resp = self.ba.handle_blockage_migration(req).unwrap(); - blockage_migration::handle_response(state, resp, &self.ba.lox_pub).unwrap() + let encoded: Vec = bincode::serialize(&req).unwrap(); + let req_t = req_start.elapsed(); + let req_len = encoded.len(); + + let resp_start = Instant::now(); + let decoded = bincode::deserialize(&encoded[..]).unwrap(); + let resp = self.ba.handle_blockage_migration(decoded).unwrap(); + let encoded_resp: Vec = bincode::serialize(&resp).unwrap(); + let resp_t = resp_start.elapsed(); + let resp_len = encoded_resp.len(); + + let resp_handle_start = Instant::now(); + let decode_resp: blockage_migration::Response = + bincode::deserialize(&encoded_resp[..]).unwrap(); + let cred = + blockage_migration::handle_response(state, decode_resp, &self.ba.lox_pub).unwrap(); + let resp_handle_t = resp_handle_start.elapsed(); + + return ( + PerfStat { + req_len, + resp_len, + req_t, + resp_t, + resp_handle_t, + }, + cred, + ); } } @@ -207,7 +398,7 @@ fn test_trust_promotion() { // Time passes th.advance_days(47); - let migcred = th.trust_promotion(&cred); + let (perf_stat, migcred) = th.trust_promotion(&cred); assert!(th.ba.verify_migration(&migcred)); // Check that we can use the to_bucket in the Migration credenital @@ -216,6 +407,11 @@ fn test_trust_promotion() { let encbuckets = th.ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); + println!("Request size = {:?}", perf_stat.req_len); + println!("Request time = {:?}", perf_stat.req_t); + println!("Response size = {:?}", perf_stat.resp_len); + println!("Response time = {:?}", perf_stat.resp_t); + println!("Response handle time = {:?}", perf_stat.resp_handle_t); println!("bucket = {:?}", bucket); assert!(th.ba.verify_reachability(&bucket.1.unwrap())); } @@ -230,10 +426,39 @@ fn test_level0_migration() { // Time passes th.advance_days(47); - let migcred = th.trust_promotion(&cred); + let (perf_stat, migcred) = th.trust_promotion(&cred); assert!(th.ba.verify_migration(&migcred)); + println!( + "Trust Promotion to 1 Request size = {:?}", + perf_stat.req_len + ); + println!("Trust Promotion to 1 Request time = {:?}", perf_stat.req_t); + println!( + "Trust Promotion to 1 Response size = {:?}", + perf_stat.resp_len + ); + println!( + "Trust Promotion to 1 Response time = {:?}", + perf_stat.resp_t + ); + println!( + "Trust Promotion to 1 Response handle time = {:?}", + perf_stat.resp_handle_t + ); - let newloxcred = th.level0_migration(&cred, &migcred); + let (mperf_stat, newloxcred) = th.level0_migration(&cred, &migcred); + + println!("Level 0 migration Request size = {:?}", mperf_stat.req_len); + println!("Level 0 migration Request time = {:?}", mperf_stat.req_t); + println!( + "Level 0 migration Response size = {:?}", + mperf_stat.resp_len + ); + println!("Level 0 migration Response time = {:?}", mperf_stat.resp_t); + println!( + "Level 0 migration Response handle time = {:?}", + perf_stat.resp_handle_t + ); assert!(th.ba.verify_lox(&newloxcred)); println!("newloxcred = {:?}", newloxcred); @@ -257,32 +482,132 @@ fn test_level_up() { th.advance_days(47); // Go up to level 1 - let migcred = th.trust_promotion(&cred); - let cred1 = th.level0_migration(&cred, &migcred); + let (perf_stat, migcred) = th.trust_promotion(&cred); + println!( + "Trust Promotion to 1 Request size = {:?}", + perf_stat.req_len + ); + println!("Trust Promotion to 1 Request time = {:?}", perf_stat.req_t); + println!( + "Trust Promotion to 1 Response size = {:?}", + perf_stat.resp_len + ); + println!( + "Trust Promotion to 1 Response time = {:?}", + perf_stat.resp_t + ); + println!( + "Trust Promotion to 1 Response handle time = {:?}", + perf_stat.resp_handle_t + ); + + let (mperf_stat, cred1) = th.level0_migration(&cred, &migcred); + + println!( + "New Level 1 credential Request size = {:?}", + mperf_stat.req_len + ); + println!( + "New Level 1 credential Request time = {:?}", + mperf_stat.req_t + ); + println!( + "New Level 1 credential Response size = {:?}", + mperf_stat.resp_len + ); + println!( + "New Level 1 credential Response time = {:?}", + mperf_stat.resp_t + ); + println!( + "New Level 1 credential Response handle time = {:?}", + perf_stat.resp_handle_t + ); + assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes th.advance_days(20); - let cred2 = th.level_up(&cred1); + let (two_perf_stat, cred2) = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); + println!( + "Trust Promotion to 2 Request size = {:?}", + two_perf_stat.req_len + ); + println!( + "Trust Promotion to 2 Request time = {:?}", + two_perf_stat.req_t + ); + println!( + "Trust Promotion to 2 Response size = {:?}", + two_perf_stat.resp_len + ); + println!( + "Trust Promotion to 2 Response time = {:?}", + two_perf_stat.resp_t + ); + println!( + "Trust Promotion to 2 Response handle time = {:?}", + two_perf_stat.resp_handle_t + ); assert!(th.ba.verify_lox(&cred2)); // Time passes th.advance_days(30); - let cred3 = th.level_up(&cred2); + let (three_perf_stat, cred3) = th.level_up(&cred2); assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); println!("cred3 = {:?}", cred3); + println!( + "Trust Promotion to 3 Request size = {:?}", + three_perf_stat.req_len + ); + println!( + "Trust Promotion to 3 Request time = {:?}", + three_perf_stat.req_t + ); + println!( + "Trust Promotion to 3 Response size = {:?}", + three_perf_stat.resp_len + ); + println!( + "Trust Promotion to 3 Response time = {:?}", + three_perf_stat.resp_t + ); + println!( + "Trust Promotion to 3 Response handle time = {:?}", + three_perf_stat.resp_handle_t + ); assert!(th.ba.verify_lox(&cred3)); // Time passes th.advance_days(60); - let cred4 = th.level_up(&cred3); + let (four_perf_stat, cred4) = th.level_up(&cred3); assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); println!("cred4 = {:?}", cred4); + println!( + "Trust Promotion to 4 Request size = {:?}", + four_perf_stat.req_len + ); + println!( + "Trust Promotion to 4 Request time = {:?}", + four_perf_stat.req_t + ); + println!( + "Trust Promotion to 4 Response size = {:?}", + four_perf_stat.resp_len + ); + println!( + "Trust Promotion to 4 Response time = {:?}", + four_perf_stat.resp_t + ); + println!( + "Trust Promotion to 4 Response handle time = {:?}", + four_perf_stat.resp_handle_t + ); assert!(th.ba.verify_lox(&cred4)); } @@ -297,21 +622,21 @@ fn test_issue_invite() { th.advance_days(47); // Go up to level 1 - let migcred = th.trust_promotion(&cred); - let cred1 = th.level0_migration(&cred, &migcred); + let (perf_stat, migcred) = th.trust_promotion(&cred); + let (mperf_stat, cred1) = th.level0_migration(&cred, &migcred); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes th.advance_days(20); // Go up to level 2 - let cred2 = th.level_up(&cred1); + let (two_perf_stat, cred2) = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); assert!(th.ba.verify_lox(&cred2)); // Issue an invitation - let (cred2a, invite) = th.issue_invite(&cred2); + let (invite_perf_stat, (cred2a, invite)) = th.issue_invite(&cred2); assert!(th.ba.verify_lox(&cred2a)); assert!(th.ba.verify_invitation(&invite)); println!("cred2a = {:?}", cred2a); @@ -329,21 +654,21 @@ fn test_redeem_invite() { th.advance_days(47); // Go up to level 1 - let migcred = th.trust_promotion(&cred); - let cred1 = th.level0_migration(&cred, &migcred); + let (perf_stat, migcred) = th.trust_promotion(&cred); + let (one_perf_stat, cred1) = th.level0_migration(&cred, &migcred); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes th.advance_days(20); // Go up to level 2 - let cred2 = th.level_up(&cred1); + let (two_perf_stat, cred2) = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); assert!(th.ba.verify_lox(&cred2)); // Issue an invitation to Bob - let (cred2a, bob_invite) = th.issue_invite(&cred2); + let (invite_perf_stat, (cred2a, bob_invite)) = th.issue_invite(&cred2); assert!(th.ba.verify_lox(&cred2a)); assert!(th.ba.verify_invitation(&bob_invite)); println!("cred2a = {:?}", cred2a); @@ -353,7 +678,7 @@ fn test_redeem_invite() { th.advance_days(12); // Bob joins the system - let bob_cred = th.redeem_invite(&bob_invite); + let (bob_perf_stat, bob_cred) = th.redeem_invite(&bob_invite); assert!(th.ba.verify_lox(&bob_cred)); println!("bob_cred = {:?}", bob_cred); } @@ -419,15 +744,15 @@ fn test_blockage_migration() { th.advance_days(47); // Go up to level 1 - let migcred = th.trust_promotion(&cred); - let cred1 = th.level0_migration(&cred, &migcred); + let (mperf_stat, migcred) = th.trust_promotion(&cred); + let (perf_stat, cred1) = th.level0_migration(&cred, &migcred); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes th.advance_days(20); // Go up to level 2 - let cred2 = th.level_up(&cred1); + let (two_perf_stat, cred2) = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); assert!(th.ba.verify_lox(&cred2)); @@ -436,7 +761,7 @@ fn test_blockage_migration() { th.advance_days(29); // Go up to level 3 - let cred3 = th.level_up(&cred2); + let (three_perf_stat, cred3) = th.level_up(&cred2); assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); println!("cred3 = {:?}", cred3); assert!(th.ba.verify_lox(&cred3)); @@ -468,12 +793,12 @@ fn test_blockage_migration() { assert!(bucket2.1.is_none()); // See about getting a Migration credential for the blockage - let migration = th.check_blockage(&cred3); + let (block_perf_stat, migration) = th.check_blockage(&cred3); println!("migration = {:?}", migration); // Migrate - let cred4 = th.blockage_migration(&cred3, &migration); + let (four_perf_stat, cred4) = th.blockage_migration(&cred3, &migration); println!("cred4 = {:?}", cred4); assert!(th.ba.verify_lox(&cred4)); From 62172528136065e30f19f0fbf1bddbc32269ff69 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Tue, 15 Jun 2021 02:01:24 -0400 Subject: [PATCH 058/115] Added statistics for open invite 1000 users --- crates/lox-library/Cargo.toml | 1 + crates/lox-library/src/tests.rs | 169 ++++++++++++++++++++++++++++---- 2 files changed, 153 insertions(+), 17 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index 4142439..3d50805 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -14,6 +14,7 @@ rand = "0.7" serde = "1" serde_with = "1.9.1" sha2 = "0.9" +statistical = "1.0.0" lazy_static = "1" hex_fmt = "0.3" aes-gcm = "0.8" diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 32e5de6..f1826e4 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -4,6 +4,7 @@ BridgeLine::random() or private fields */ use super::bridge_table::BridgeLine; use super::proto::*; use super::*; +use statistical::{mean, standard_deviation}; use std::time::{Duration, Instant}; struct PerfStat { @@ -22,13 +23,17 @@ struct TestHarness { impl TestHarness { fn new() -> Self { + TestHarness::new_buckets(5, 5) + } + + fn new_buckets(num_buckets: u8, hot_spare: u8) -> Self { // Create a BridegDb let mut bdb = BridgeDb::new(); // Create a BridgeAuth let mut ba = BridgeAuth::new(bdb.pubkey); // Make 15 open invitation bridges, in 5 sets of 3 - for _ in 0..5 { + for _ in 0..num_buckets { let bucket = [ BridgeLine::random(), BridgeLine::random(), @@ -37,7 +42,7 @@ impl TestHarness { ba.add_openinv_bridges(bucket, &mut bdb); } // Add 5 more hot spare buckets - for _ in 0..5 { + for _ in 0..hot_spare { let bucket = [ BridgeLine::random(), BridgeLine::random(), @@ -622,21 +627,21 @@ fn test_issue_invite() { th.advance_days(47); // Go up to level 1 - let (perf_stat, migcred) = th.trust_promotion(&cred); - let (mperf_stat, cred1) = th.level0_migration(&cred, &migcred); + let (_perf_stat, migcred) = th.trust_promotion(&cred); + let (_mperf_stat, cred1) = th.level0_migration(&cred, &migcred); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes th.advance_days(20); // Go up to level 2 - let (two_perf_stat, cred2) = th.level_up(&cred1); + let (_two_perf_stat, cred2) = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); assert!(th.ba.verify_lox(&cred2)); // Issue an invitation - let (invite_perf_stat, (cred2a, invite)) = th.issue_invite(&cred2); + let (_invite_perf_stat, (cred2a, invite)) = th.issue_invite(&cred2); assert!(th.ba.verify_lox(&cred2a)); assert!(th.ba.verify_invitation(&invite)); println!("cred2a = {:?}", cred2a); @@ -654,21 +659,21 @@ fn test_redeem_invite() { th.advance_days(47); // Go up to level 1 - let (perf_stat, migcred) = th.trust_promotion(&cred); - let (one_perf_stat, cred1) = th.level0_migration(&cred, &migcred); + let (_perf_stat, migcred) = th.trust_promotion(&cred); + let (_one_perf_stat, cred1) = th.level0_migration(&cred, &migcred); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes th.advance_days(20); // Go up to level 2 - let (two_perf_stat, cred2) = th.level_up(&cred1); + let (_two_perf_stat, cred2) = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); assert!(th.ba.verify_lox(&cred2)); // Issue an invitation to Bob - let (invite_perf_stat, (cred2a, bob_invite)) = th.issue_invite(&cred2); + let (_invite_perf_stat, (cred2a, bob_invite)) = th.issue_invite(&cred2); assert!(th.ba.verify_lox(&cred2a)); assert!(th.ba.verify_invitation(&bob_invite)); println!("cred2a = {:?}", cred2a); @@ -678,7 +683,7 @@ fn test_redeem_invite() { th.advance_days(12); // Bob joins the system - let (bob_perf_stat, bob_cred) = th.redeem_invite(&bob_invite); + let (_bob_perf_stat, bob_cred) = th.redeem_invite(&bob_invite); assert!(th.ba.verify_lox(&bob_cred)); println!("bob_cred = {:?}", bob_cred); } @@ -744,15 +749,15 @@ fn test_blockage_migration() { th.advance_days(47); // Go up to level 1 - let (mperf_stat, migcred) = th.trust_promotion(&cred); - let (perf_stat, cred1) = th.level0_migration(&cred, &migcred); + let (_mperf_stat, migcred) = th.trust_promotion(&cred); + let (_perf_stat, cred1) = th.level0_migration(&cred, &migcred); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes th.advance_days(20); // Go up to level 2 - let (two_perf_stat, cred2) = th.level_up(&cred1); + let (_two_perf_stat, cred2) = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); assert!(th.ba.verify_lox(&cred2)); @@ -761,7 +766,7 @@ fn test_blockage_migration() { th.advance_days(29); // Go up to level 3 - let (three_perf_stat, cred3) = th.level_up(&cred2); + let (_three_perf_stat, cred3) = th.level_up(&cred2); assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); println!("cred3 = {:?}", cred3); assert!(th.ba.verify_lox(&cred3)); @@ -793,13 +798,143 @@ fn test_blockage_migration() { assert!(bucket2.1.is_none()); // See about getting a Migration credential for the blockage - let (block_perf_stat, migration) = th.check_blockage(&cred3); + let (_block_perf_stat, migration) = th.check_blockage(&cred3); println!("migration = {:?}", migration); // Migrate - let (four_perf_stat, cred4) = th.blockage_migration(&cred3, &migration); + let (_four_perf_stat, cred4) = th.blockage_migration(&cred3, &migration); println!("cred4 = {:?}", cred4); assert!(th.ba.verify_lox(&cred4)); } + +#[test] +fn protocol_tests() { + let mut th = TestHarness::new_buckets(10, 10); + let mut req_size: Vec = Vec::new(); + let mut resp_size: Vec = Vec::new(); + let mut req_t_size: Vec = Vec::new(); + let mut resp_t_size: Vec = Vec::new(); + let mut resp_handle_t_size: Vec = Vec::new(); + for _i in 0..1000 { + let (perf_stat, (_cred, _bridgeline)) = th.open_invite(); + req_size.push(perf_stat.req_len as f64); + req_t_size.push(perf_stat.req_t.as_secs_f64()); + resp_size.push(perf_stat.resp_len as f64); + resp_t_size.push(perf_stat.resp_t.as_secs_f64()); + resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); + } + let mean_req_size = mean(&req_size); + let req_std_dev = standard_deviation(&req_size, Some(mean_req_size)); + let mean_req_t_size = mean(&req_t_size); + let req_t_std_dev = standard_deviation(&req_t_size, Some(mean_req_t_size)); + let mean_resp_size = mean(&resp_size); + let resp_std_dev = standard_deviation(&resp_size, Some(mean_resp_size)); + let mean_resp_t_size = mean(&resp_t_size); + let resp_t_std_dev = standard_deviation(&resp_t_size, Some(mean_resp_t_size)); + let mean_resp_handle_t_size = mean(&resp_t_size); + let resp_handle_t_std_dev = + standard_deviation(&resp_handle_t_size, Some(mean_resp_handle_t_size)); + + println!("Average Request Size = {:?}", mean_req_size); + println!("Request Standard Deviation = {:?}", req_std_dev); + println!( + "Average Request Time = {:?}", + Duration::from_secs_f64(mean_req_t_size) + ); + println!( + "Request time Standard Deviation = {:?}", + Duration::from_secs_f64(req_t_std_dev) + ); + println!("Average Response Size = {:?}", mean_resp_size); + println!("Response Standard Deviation = {:?}", resp_std_dev); + println!( + "Average Response Time = {:?}", + Duration::from_secs_f64(mean_resp_t_size) + ); + println!( + "Response Time Standard Deviation = {:?}", + Duration::from_secs_f64(resp_t_std_dev) + ); + println!( + "Average Response Handling Time = {:?}", + Duration::from_secs_f64(mean_resp_handle_t_size) + ); + println!( + "Response Handling Time Standard Deviation = {:?}", + Duration::from_secs_f64(resp_handle_t_std_dev) + ); + + println!("\n---------------Block Bridges-------------------\n"); + + // Mark 5 bridges in untrusted buckets as unreachable + let b0 = th.ba.bridge_table.buckets[0][0]; + th.ba.bridge_unreachable(&b0, &mut th.bdb); + + let b3 = th.ba.bridge_table.buckets[3][0]; + th.ba.bridge_unreachable(&b3, &mut th.bdb); + + let b6 = th.ba.bridge_table.buckets[6][0]; + th.ba.bridge_unreachable(&b6, &mut th.bdb); + + let b9 = th.ba.bridge_table.buckets[9][0]; + th.ba.bridge_unreachable(&b9, &mut th.bdb); + + let b12 = th.ba.bridge_table.buckets[12][0]; + th.ba.bridge_unreachable(&b12, &mut th.bdb); + + let mut req_size2: Vec = Vec::new(); + let mut resp_size2: Vec = Vec::new(); + let mut req_t_size2: Vec = Vec::new(); + let mut resp_t_size2: Vec = Vec::new(); + let mut resp_handle_t_size2: Vec = Vec::new(); + for _i in 0..1000 { + let (perf_stat2, (_cred2, _bridgeline2)) = th.open_invite(); + req_size2.push(perf_stat2.req_len as f64); + req_t_size2.push(perf_stat2.req_t.as_secs_f64()); + resp_size2.push(perf_stat2.resp_len as f64); + resp_t_size2.push(perf_stat2.resp_t.as_secs_f64()); + resp_handle_t_size2.push(perf_stat2.resp_handle_t.as_secs_f64()); + } + let mean_req_size2 = mean(&req_size2); + let req_std_dev2 = standard_deviation(&req_size2, Some(mean_req_size2)); + let mean_req_t_size2 = mean(&req_t_size2); + let req_t_std_dev2 = standard_deviation(&req_t_size2, Some(mean_req_t_size2)); + let mean_resp_size2 = mean(&resp_size2); + let resp_std_dev2 = standard_deviation(&resp_size2, Some(mean_resp_size2)); + let mean_resp_t_size2 = mean(&resp_t_size2); + let resp_t_std_dev2 = standard_deviation(&resp_t_size2, Some(mean_resp_t_size2)); + let mean_resp_handle_t_size2 = mean(&resp_t_size2); + let resp_handle_t_std_dev2 = + standard_deviation(&resp_handle_t_size2, Some(mean_resp_handle_t_size2)); + + println!("Average Request size = {:?}", mean_req_size2); + println!("Request Standard Deviation = {:?}", req_std_dev2); + println!( + "Average Request Time = {:?}", + Duration::from_secs_f64(mean_req_t_size) + ); + println!( + "Request time Standard Deviation = {:?}", + Duration::from_secs_f64(req_t_std_dev2) + ); + println!("Average Response size = {:?}", mean_resp_size2); + println!("Response Standard Deviation = {:?}", resp_std_dev2); + println!( + "Average Response Time = {:?}", + Duration::from_secs_f64(mean_resp_t_size2) + ); + println!( + "Response Time Standard Deviation = {:?}", + Duration::from_secs_f64(resp_t_std_dev2) + ); + println!( + "Average Response Handling Time = {:?}", + Duration::from_secs_f64(mean_resp_handle_t_size2) + ); + println!( + "Response Handling Time Standard Deviation = {:?}", + Duration::from_secs_f64(resp_handle_t_std_dev2) + ); +} From 695421f265b93099c8461af0542ce146c08c9867 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 21 Jun 2021 12:05:35 -0400 Subject: [PATCH 059/115] Fixed issues identified during live code review --- crates/lox-library/src/tests.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index f1826e4..cebbe95 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -32,7 +32,7 @@ impl TestHarness { // Create a BridgeAuth let mut ba = BridgeAuth::new(bdb.pubkey); - // Make 15 open invitation bridges, in 5 sets of 3 + // Make 3 x num_buckets open invitation bridges, in sets of 3 for _ in 0..num_buckets { let bucket = [ BridgeLine::random(), @@ -41,7 +41,7 @@ impl TestHarness { ]; ba.add_openinv_bridges(bucket, &mut bdb); } - // Add 5 more hot spare buckets + // Add hot_spare more hot spare buckets for _ in 0..hot_spare { let bucket = [ BridgeLine::random(), @@ -817,8 +817,8 @@ fn protocol_tests() { let mut req_t_size: Vec = Vec::new(); let mut resp_t_size: Vec = Vec::new(); let mut resp_handle_t_size: Vec = Vec::new(); - for _i in 0..1000 { - let (perf_stat, (_cred, _bridgeline)) = th.open_invite(); + for _ in 0..1000 { + let (perf_stat, _) = th.open_invite(); req_size.push(perf_stat.req_len as f64); req_t_size.push(perf_stat.req_t.as_secs_f64()); resp_size.push(perf_stat.resp_len as f64); @@ -837,8 +837,8 @@ fn protocol_tests() { let resp_handle_t_std_dev = standard_deviation(&resp_handle_t_size, Some(mean_resp_handle_t_size)); - println!("Average Request Size = {:?}", mean_req_size); - println!("Request Standard Deviation = {:?}", req_std_dev); + println!("Average Request Size = {}", mean_req_size); + println!("Request Standard Deviation = {}", req_std_dev); println!( "Average Request Time = {:?}", Duration::from_secs_f64(mean_req_t_size) @@ -847,8 +847,8 @@ fn protocol_tests() { "Request time Standard Deviation = {:?}", Duration::from_secs_f64(req_t_std_dev) ); - println!("Average Response Size = {:?}", mean_resp_size); - println!("Response Standard Deviation = {:?}", resp_std_dev); + println!("Average Response Size = {}", mean_resp_size); + println!("Response Standard Deviation = {}", resp_std_dev); println!( "Average Response Time = {:?}", Duration::from_secs_f64(mean_resp_t_size) @@ -889,8 +889,8 @@ fn protocol_tests() { let mut req_t_size2: Vec = Vec::new(); let mut resp_t_size2: Vec = Vec::new(); let mut resp_handle_t_size2: Vec = Vec::new(); - for _i in 0..1000 { - let (perf_stat2, (_cred2, _bridgeline2)) = th.open_invite(); + for _ in 0..1000 { + let (perf_stat2, _) = th.open_invite(); req_size2.push(perf_stat2.req_len as f64); req_t_size2.push(perf_stat2.req_t.as_secs_f64()); resp_size2.push(perf_stat2.resp_len as f64); @@ -909,8 +909,8 @@ fn protocol_tests() { let resp_handle_t_std_dev2 = standard_deviation(&resp_handle_t_size2, Some(mean_resp_handle_t_size2)); - println!("Average Request size = {:?}", mean_req_size2); - println!("Request Standard Deviation = {:?}", req_std_dev2); + println!("Average Request size = {}", mean_req_size2); + println!("Request Standard Deviation = {}", req_std_dev2); println!( "Average Request Time = {:?}", Duration::from_secs_f64(mean_req_t_size) @@ -919,8 +919,8 @@ fn protocol_tests() { "Request time Standard Deviation = {:?}", Duration::from_secs_f64(req_t_std_dev2) ); - println!("Average Response size = {:?}", mean_resp_size2); - println!("Response Standard Deviation = {:?}", resp_std_dev2); + println!("Average Response size = {}", mean_resp_size2); + println!("Response Standard Deviation = {}", resp_std_dev2); println!( "Average Response Time = {:?}", Duration::from_secs_f64(mean_resp_t_size2) From 95615cf3eeb6c7647ed29851e274926f338a64a4 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Tue, 22 Jun 2021 14:43:15 -0400 Subject: [PATCH 060/115] Modularized duplicate code and added more tests --- crates/lox-library/src/tests.rs | 497 ++++++++++++++++++-------------- 1 file changed, 278 insertions(+), 219 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index cebbe95..a2f87c3 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -380,11 +380,7 @@ fn test_open_invite() { let encbuckets = th.ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); - println!("Request size = {:?}", perf_stat.req_len); - println!("Request time = {:?}", perf_stat.req_t); - println!("Response size = {:?}", perf_stat.resp_len); - println!("Response time = {:?}", perf_stat.resp_t); - println!("Response handle time = {:?}", perf_stat.resp_handle_t); + print_test_results(perf_stat); println!("cred = {:?}", cred); println!("bucket = {:?}", bucket); println!("bridgeline = {:?}", bridgeline); @@ -412,11 +408,7 @@ fn test_trust_promotion() { let encbuckets = th.ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); - println!("Request size = {:?}", perf_stat.req_len); - println!("Request time = {:?}", perf_stat.req_t); - println!("Response size = {:?}", perf_stat.resp_len); - println!("Response time = {:?}", perf_stat.resp_t); - println!("Response handle time = {:?}", perf_stat.resp_handle_t); + print_test_results(perf_stat); println!("bucket = {:?}", bucket); assert!(th.ba.verify_reachability(&bucket.1.unwrap())); } @@ -433,37 +425,13 @@ fn test_level0_migration() { let (perf_stat, migcred) = th.trust_promotion(&cred); assert!(th.ba.verify_migration(&migcred)); - println!( - "Trust Promotion to 1 Request size = {:?}", - perf_stat.req_len - ); - println!("Trust Promotion to 1 Request time = {:?}", perf_stat.req_t); - println!( - "Trust Promotion to 1 Response size = {:?}", - perf_stat.resp_len - ); - println!( - "Trust Promotion to 1 Response time = {:?}", - perf_stat.resp_t - ); - println!( - "Trust Promotion to 1 Response handle time = {:?}", - perf_stat.resp_handle_t - ); + println!("--Trust Promotion to 1--\n"); + print_test_results(perf_stat); let (mperf_stat, newloxcred) = th.level0_migration(&cred, &migcred); - println!("Level 0 migration Request size = {:?}", mperf_stat.req_len); - println!("Level 0 migration Request time = {:?}", mperf_stat.req_t); - println!( - "Level 0 migration Response size = {:?}", - mperf_stat.resp_len - ); - println!("Level 0 migration Response time = {:?}", mperf_stat.resp_t); - println!( - "Level 0 migration Response handle time = {:?}", - perf_stat.resp_handle_t - ); + println!("--Level 0 migration--\n"); + print_test_results(mperf_stat); assert!(th.ba.verify_lox(&newloxcred)); println!("newloxcred = {:?}", newloxcred); @@ -488,46 +456,14 @@ fn test_level_up() { // Go up to level 1 let (perf_stat, migcred) = th.trust_promotion(&cred); - println!( - "Trust Promotion to 1 Request size = {:?}", - perf_stat.req_len - ); - println!("Trust Promotion to 1 Request time = {:?}", perf_stat.req_t); - println!( - "Trust Promotion to 1 Response size = {:?}", - perf_stat.resp_len - ); - println!( - "Trust Promotion to 1 Response time = {:?}", - perf_stat.resp_t - ); - println!( - "Trust Promotion to 1 Response handle time = {:?}", - perf_stat.resp_handle_t - ); + + println!("--Trust Promotion to 1--\n"); + print_test_results(perf_stat); let (mperf_stat, cred1) = th.level0_migration(&cred, &migcred); - println!( - "New Level 1 credential Request size = {:?}", - mperf_stat.req_len - ); - println!( - "New Level 1 credential Request time = {:?}", - mperf_stat.req_t - ); - println!( - "New Level 1 credential Response size = {:?}", - mperf_stat.resp_len - ); - println!( - "New Level 1 credential Response time = {:?}", - mperf_stat.resp_t - ); - println!( - "New Level 1 credential Response handle time = {:?}", - perf_stat.resp_handle_t - ); + println!("--New Level 1 Credential--\n"); + print_test_results(mperf_stat); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); @@ -536,27 +472,10 @@ fn test_level_up() { let (two_perf_stat, cred2) = th.level_up(&cred1); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); + + println!("--Upgrade to Level 2--\n"); + print_test_results(two_perf_stat); println!("cred2 = {:?}", cred2); - println!( - "Trust Promotion to 2 Request size = {:?}", - two_perf_stat.req_len - ); - println!( - "Trust Promotion to 2 Request time = {:?}", - two_perf_stat.req_t - ); - println!( - "Trust Promotion to 2 Response size = {:?}", - two_perf_stat.resp_len - ); - println!( - "Trust Promotion to 2 Response time = {:?}", - two_perf_stat.resp_t - ); - println!( - "Trust Promotion to 2 Response handle time = {:?}", - two_perf_stat.resp_handle_t - ); assert!(th.ba.verify_lox(&cred2)); // Time passes @@ -564,27 +483,9 @@ fn test_level_up() { let (three_perf_stat, cred3) = th.level_up(&cred2); assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); + println!("--Upgrade to Level 3--\n"); + print_test_results(three_perf_stat); println!("cred3 = {:?}", cred3); - println!( - "Trust Promotion to 3 Request size = {:?}", - three_perf_stat.req_len - ); - println!( - "Trust Promotion to 3 Request time = {:?}", - three_perf_stat.req_t - ); - println!( - "Trust Promotion to 3 Response size = {:?}", - three_perf_stat.resp_len - ); - println!( - "Trust Promotion to 3 Response time = {:?}", - three_perf_stat.resp_t - ); - println!( - "Trust Promotion to 3 Response handle time = {:?}", - three_perf_stat.resp_handle_t - ); assert!(th.ba.verify_lox(&cred3)); // Time passes @@ -592,27 +493,9 @@ fn test_level_up() { let (four_perf_stat, cred4) = th.level_up(&cred3); assert!(scalar_u32(&cred3.trust_level).unwrap() == 3); + println!("--Upgrade to Level 4--\n"); + print_test_results(four_perf_stat); println!("cred4 = {:?}", cred4); - println!( - "Trust Promotion to 4 Request size = {:?}", - four_perf_stat.req_len - ); - println!( - "Trust Promotion to 4 Request time = {:?}", - four_perf_stat.req_t - ); - println!( - "Trust Promotion to 4 Response size = {:?}", - four_perf_stat.resp_len - ); - println!( - "Trust Promotion to 4 Response time = {:?}", - four_perf_stat.resp_t - ); - println!( - "Trust Promotion to 4 Response handle time = {:?}", - four_perf_stat.resp_handle_t - ); assert!(th.ba.verify_lox(&cred4)); } @@ -627,21 +510,29 @@ fn test_issue_invite() { th.advance_days(47); // Go up to level 1 - let (_perf_stat, migcred) = th.trust_promotion(&cred); - let (_mperf_stat, cred1) = th.level0_migration(&cred, &migcred); + let (perf_stat, migcred) = th.trust_promotion(&cred); + println!("--Trust Promotion to 1--\n"); + print_test_results(perf_stat); + let (mperf_stat, cred1) = th.level0_migration(&cred, &migcred); + println!("--New Level 1 Credential--\n"); + print_test_results(mperf_stat); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes th.advance_days(20); // Go up to level 2 - let (_two_perf_stat, cred2) = th.level_up(&cred1); + let (two_perf_stat, cred2) = th.level_up(&cred1); + println!("--Upgrade to Level 2--\n"); + print_test_results(two_perf_stat); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); assert!(th.ba.verify_lox(&cred2)); // Issue an invitation - let (_invite_perf_stat, (cred2a, invite)) = th.issue_invite(&cred2); + let (invite_perf_stat, (cred2a, invite)) = th.issue_invite(&cred2); + println!("--Issue Invitation--\n"); + print_test_results(invite_perf_stat); assert!(th.ba.verify_lox(&cred2a)); assert!(th.ba.verify_invitation(&invite)); println!("cred2a = {:?}", cred2a); @@ -659,21 +550,29 @@ fn test_redeem_invite() { th.advance_days(47); // Go up to level 1 - let (_perf_stat, migcred) = th.trust_promotion(&cred); - let (_one_perf_stat, cred1) = th.level0_migration(&cred, &migcred); + let (perf_stat, migcred) = th.trust_promotion(&cred); + println!("--Trust Promotion to 1--\n"); + print_test_results(perf_stat); + let (mperf_stat, cred1) = th.level0_migration(&cred, &migcred); + println!("--New Level 1 Credential--\n"); + print_test_results(mperf_stat); assert!(scalar_u32(&cred1.trust_level).unwrap() == 1); // Time passes th.advance_days(20); // Go up to level 2 - let (_two_perf_stat, cred2) = th.level_up(&cred1); + let (two_perf_stat, cred2) = th.level_up(&cred1); + println!("--Upgrade to Level 2--\n"); + print_test_results(two_perf_stat); assert!(scalar_u32(&cred2.trust_level).unwrap() == 2); println!("cred2 = {:?}", cred2); assert!(th.ba.verify_lox(&cred2)); // Issue an invitation to Bob - let (_invite_perf_stat, (cred2a, bob_invite)) = th.issue_invite(&cred2); + let (invite_perf_stat, (cred2a, bob_invite)) = th.issue_invite(&cred2); + println!("--Issue Invitation--\n"); + print_test_results(invite_perf_stat); assert!(th.ba.verify_lox(&cred2a)); assert!(th.ba.verify_invitation(&bob_invite)); println!("cred2a = {:?}", cred2a); @@ -683,7 +582,9 @@ fn test_redeem_invite() { th.advance_days(12); // Bob joins the system - let (_bob_perf_stat, bob_cred) = th.redeem_invite(&bob_invite); + let (bob_perf_stat, bob_cred) = th.redeem_invite(&bob_invite); + println!("--Bob joins the system--\n"); + print_test_results(bob_perf_stat); assert!(th.ba.verify_lox(&bob_cred)); println!("bob_cred = {:?}", bob_cred); } @@ -810,8 +711,10 @@ fn test_blockage_migration() { } #[test] -fn protocol_tests() { +fn stats_test_open_invite() { let mut th = TestHarness::new_buckets(10, 10); + + println!("\n---------------Open Invitationn-------------------\n"); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); let mut req_t_size: Vec = Vec::new(); @@ -825,6 +728,234 @@ fn protocol_tests() { resp_t_size.push(perf_stat.resp_t.as_secs_f64()); resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); } + + print_stats_test_results( + req_size, + req_t_size, + resp_size, + resp_t_size, + resp_handle_t_size, + ); +} + +#[test] +fn stats_test_trust_promotion() { + let mut th = TestHarness::new_buckets(10, 10); + println!("\n-------Trust Promotion--------\n"); + + let mut req_size: Vec = Vec::new(); + let mut resp_size: Vec = Vec::new(); + let mut req_t_size: Vec = Vec::new(); + let mut resp_t_size: Vec = Vec::new(); + let mut resp_handle_t_size: Vec = Vec::new(); + for _ in 0..1000 { + let cred = th.open_invite().1 .0; + th.advance_days(47); + let (perf_stat, _) = th.trust_promotion(&cred); + req_size.push(perf_stat.req_len as f64); + req_t_size.push(perf_stat.req_t.as_secs_f64()); + resp_size.push(perf_stat.resp_len as f64); + resp_t_size.push(perf_stat.resp_t.as_secs_f64()); + resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); + } + + print_stats_test_results( + req_size, + req_t_size, + resp_size, + resp_t_size, + resp_handle_t_size, + ); +} + +#[test] +fn stats_test_trust_level0_migration() { + let mut th = TestHarness::new_buckets(10, 10); + + println!("\n-------------Trust Level0 Migration----------------\n"); + let mut req_size: Vec = Vec::new(); + let mut resp_size: Vec = Vec::new(); + let mut req_t_size: Vec = Vec::new(); + let mut resp_t_size: Vec = Vec::new(); + let mut resp_handle_t_size: Vec = Vec::new(); + let mut tot_req_size: Vec = Vec::new(); + let mut tot_resp_size: Vec = Vec::new(); + let mut tot_req_t_size: Vec = Vec::new(); + let mut tot_resp_t_size: Vec = Vec::new(); + let mut tot_resp_handle_t_size: Vec = Vec::new(); + for _ in 0..1000 { + let cred = th.open_invite().1 .0; + th.advance_days(47); + let (tp_perf_stat, migcred) = th.trust_promotion(&cred); + let (perf_stat, _) = th.level0_migration(&cred, &migcred); + req_size.push(perf_stat.req_len as f64); + req_t_size.push(perf_stat.req_t.as_secs_f64()); + resp_size.push(perf_stat.resp_len as f64); + resp_t_size.push(perf_stat.resp_t.as_secs_f64()); + resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); + tot_req_size.push((perf_stat.req_len + tp_perf_stat.req_len) as f64); + tot_req_t_size.push((perf_stat.req_t + tp_perf_stat.req_t).as_secs_f64()); + tot_resp_size.push((perf_stat.resp_len + tp_perf_stat.resp_len) as f64); + tot_resp_t_size.push((perf_stat.resp_t + tp_perf_stat.resp_t).as_secs_f64()); + tot_resp_handle_t_size + .push((perf_stat.resp_handle_t + tp_perf_stat.resp_handle_t).as_secs_f64()); + } + + print_stats_test_results( + req_size, + req_t_size, + resp_size, + resp_t_size, + resp_handle_t_size, + ); + + println!("\n-------Total Trust Promotion to Level 1-------\n"); + print_stats_test_results( + tot_req_size, + tot_req_t_size, + tot_resp_size, + tot_resp_t_size, + tot_resp_handle_t_size, + ); +} + + +#[test] +fn stats_test_trust_level_up() { + let mut th = TestHarness::new_buckets(10, 10); + + println!("\n-------------Trust Level0 Migration----------------\n"); + let mut req_size: Vec = Vec::new(); + let mut resp_size: Vec = Vec::new(); + let mut req_t_size: Vec = Vec::new(); + let mut resp_t_size: Vec = Vec::new(); + let mut resp_handle_t_size: Vec = Vec::new(); + let mut tot_req_size: Vec = Vec::new(); + let mut tot_resp_size: Vec = Vec::new(); + let mut tot_req_t_size: Vec = Vec::new(); + let mut tot_resp_t_size: Vec = Vec::new(); + let mut tot_resp_handle_t_size: Vec = Vec::new(); + for _ in 0..1000 { + let cred = th.open_invite().1 .0; + th.advance_days(47); + let (tp_perf_stat, migcred) = th.trust_promotion(&cred); + let (perf_stat, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(20); + let (two_perf_stat, cred2) = th.level_up(&cred1); + th.advance_days(30); + let (three_perf_stat, cred3) = th.level_up(&cred2); + th.advance_days(60); + let (four_perf_stat, cred3) = th.level_up(&cred2); + req_size.push(perf_stat.req_len as f64); + req_t_size.push(perf_stat.req_t.as_secs_f64()); + resp_size.push(perf_stat.resp_len as f64); + resp_t_size.push(perf_stat.resp_t.as_secs_f64()); + resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); + tot_req_size.push((perf_stat.req_len + tp_perf_stat.req_len) as f64); + tot_req_t_size.push((perf_stat.req_t + tp_perf_stat.req_t).as_secs_f64()); + tot_resp_size.push((perf_stat.resp_len + tp_perf_stat.resp_len) as f64); + tot_resp_t_size.push((perf_stat.resp_t + tp_perf_stat.resp_t).as_secs_f64()); + tot_resp_handle_t_size + .push((perf_stat.resp_handle_t + tp_perf_stat.resp_handle_t).as_secs_f64()); + } + + print_stats_test_results( + req_size, + req_t_size, + resp_size, + resp_t_size, + resp_handle_t_size, + ); + + println!("\n-------Total Trust Promotion to Level 1-------\n"); + print_stats_test_results( + tot_req_size, + tot_req_t_size, + tot_resp_size, + tot_resp_t_size, + tot_resp_handle_t_size, + ); +} +#[test] +fn stats_test_blocked_bridges() { + let mut th = TestHarness::new_buckets(10, 10); + println!("\n-------Trust Promotion With Blocked Bridges--------\n"); + + let mut req_size_b: Vec = Vec::new(); + let mut resp_size_b: Vec = Vec::new(); + let mut req_t_size_b: Vec = Vec::new(); + let mut resp_t_size_b: Vec = Vec::new(); + let mut resp_handle_t_size_b: Vec = Vec::new(); + for _ in 0..1000 { + let cred = th.open_invite().1 .0; + th.advance_days(47); + let (perf_stat, migcred) = th.trust_promotion(&cred); + req_size_b.push(perf_stat.req_len as f64); + req_t_size_b.push(perf_stat.req_t.as_secs_f64()); + resp_size_b.push(perf_stat.resp_len as f64); + resp_t_size_b.push(perf_stat.resp_t.as_secs_f64()); + resp_handle_t_size_b.push(perf_stat.resp_handle_t.as_secs_f64()); + } + + // Mark 5 bridges in untrusted buckets as unreachable + for i in 0..50 { + if i % 2 == 0 { + let b0 = th.ba.bridge_table.buckets[i][0]; + th.ba.bridge_unreachable(&b0, &mut th.bdb); + } + } + + print_stats_test_results( + req_size_b, + req_t_size_b, + resp_size_b, + resp_t_size_b, + resp_handle_t_size_b, + ); +} + +#[test] +fn stats_test_something_else_test() { + let mut th = TestHarness::new_buckets(10, 10); + println!("\n---------------Block Bridges-------------------\n"); + + let mut req_size2: Vec = Vec::new(); + let mut resp_size2: Vec = Vec::new(); + let mut req_t_size2: Vec = Vec::new(); + let mut resp_t_size2: Vec = Vec::new(); + let mut resp_handle_t_size2: Vec = Vec::new(); + for _ in 0..1000 { + let (perf_stat2, _) = th.open_invite(); + req_size2.push(perf_stat2.req_len as f64); + req_t_size2.push(perf_stat2.req_t.as_secs_f64()); + resp_size2.push(perf_stat2.resp_len as f64); + resp_t_size2.push(perf_stat2.resp_t.as_secs_f64()); + resp_handle_t_size2.push(perf_stat2.resp_handle_t.as_secs_f64()); + } + print_stats_test_results( + req_size2, + req_t_size2, + resp_size2, + resp_t_size2, + resp_handle_t_size2, + ); +} + +fn print_test_results(perf_stat: PerfStat) { + println!("Request size = {:?}", perf_stat.req_len); + println!("Request time = {:?}", perf_stat.req_t); + println!("Response size = {:?}", perf_stat.resp_len); + println!("Response time = {:?}", perf_stat.resp_t); + println!("Response handle time = {:?}", perf_stat.resp_handle_t); +} + +fn print_stats_test_results( + req_size: Vec, + req_t_size: Vec, + resp_size: Vec, + resp_t_size: Vec, + resp_handle_t_size: Vec, +) { let mean_req_size = mean(&req_size); let req_std_dev = standard_deviation(&req_size, Some(mean_req_size)); let mean_req_t_size = mean(&req_t_size); @@ -837,7 +968,7 @@ fn protocol_tests() { let resp_handle_t_std_dev = standard_deviation(&resp_handle_t_size, Some(mean_resp_handle_t_size)); - println!("Average Request Size = {}", mean_req_size); + println!("Average Request size = {}", mean_req_size); println!("Request Standard Deviation = {}", req_std_dev); println!( "Average Request Time = {:?}", @@ -847,7 +978,7 @@ fn protocol_tests() { "Request time Standard Deviation = {:?}", Duration::from_secs_f64(req_t_std_dev) ); - println!("Average Response Size = {}", mean_resp_size); + println!("Average Response size = {}", mean_resp_size); println!("Response Standard Deviation = {}", resp_std_dev); println!( "Average Response Time = {:?}", @@ -865,76 +996,4 @@ fn protocol_tests() { "Response Handling Time Standard Deviation = {:?}", Duration::from_secs_f64(resp_handle_t_std_dev) ); - - println!("\n---------------Block Bridges-------------------\n"); - - // Mark 5 bridges in untrusted buckets as unreachable - let b0 = th.ba.bridge_table.buckets[0][0]; - th.ba.bridge_unreachable(&b0, &mut th.bdb); - - let b3 = th.ba.bridge_table.buckets[3][0]; - th.ba.bridge_unreachable(&b3, &mut th.bdb); - - let b6 = th.ba.bridge_table.buckets[6][0]; - th.ba.bridge_unreachable(&b6, &mut th.bdb); - - let b9 = th.ba.bridge_table.buckets[9][0]; - th.ba.bridge_unreachable(&b9, &mut th.bdb); - - let b12 = th.ba.bridge_table.buckets[12][0]; - th.ba.bridge_unreachable(&b12, &mut th.bdb); - - let mut req_size2: Vec = Vec::new(); - let mut resp_size2: Vec = Vec::new(); - let mut req_t_size2: Vec = Vec::new(); - let mut resp_t_size2: Vec = Vec::new(); - let mut resp_handle_t_size2: Vec = Vec::new(); - for _ in 0..1000 { - let (perf_stat2, _) = th.open_invite(); - req_size2.push(perf_stat2.req_len as f64); - req_t_size2.push(perf_stat2.req_t.as_secs_f64()); - resp_size2.push(perf_stat2.resp_len as f64); - resp_t_size2.push(perf_stat2.resp_t.as_secs_f64()); - resp_handle_t_size2.push(perf_stat2.resp_handle_t.as_secs_f64()); - } - let mean_req_size2 = mean(&req_size2); - let req_std_dev2 = standard_deviation(&req_size2, Some(mean_req_size2)); - let mean_req_t_size2 = mean(&req_t_size2); - let req_t_std_dev2 = standard_deviation(&req_t_size2, Some(mean_req_t_size2)); - let mean_resp_size2 = mean(&resp_size2); - let resp_std_dev2 = standard_deviation(&resp_size2, Some(mean_resp_size2)); - let mean_resp_t_size2 = mean(&resp_t_size2); - let resp_t_std_dev2 = standard_deviation(&resp_t_size2, Some(mean_resp_t_size2)); - let mean_resp_handle_t_size2 = mean(&resp_t_size2); - let resp_handle_t_std_dev2 = - standard_deviation(&resp_handle_t_size2, Some(mean_resp_handle_t_size2)); - - println!("Average Request size = {}", mean_req_size2); - println!("Request Standard Deviation = {}", req_std_dev2); - println!( - "Average Request Time = {:?}", - Duration::from_secs_f64(mean_req_t_size) - ); - println!( - "Request time Standard Deviation = {:?}", - Duration::from_secs_f64(req_t_std_dev2) - ); - println!("Average Response size = {}", mean_resp_size2); - println!("Response Standard Deviation = {}", resp_std_dev2); - println!( - "Average Response Time = {:?}", - Duration::from_secs_f64(mean_resp_t_size2) - ); - println!( - "Response Time Standard Deviation = {:?}", - Duration::from_secs_f64(resp_t_std_dev2) - ); - println!( - "Average Response Handling Time = {:?}", - Duration::from_secs_f64(mean_resp_handle_t_size2) - ); - println!( - "Response Handling Time Standard Deviation = {:?}", - Duration::from_secs_f64(resp_handle_t_std_dev2) - ); } From c9afa18795480fdaa669fb6e05b217cd568a02e1 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 23 Jun 2021 01:23:19 -0400 Subject: [PATCH 061/115] Added all tests but details of blockage migration --- crates/lox-library/src/tests.rs | 208 +++++++++++++++++++++++++++----- 1 file changed, 178 insertions(+), 30 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index a2f87c3..32615a6 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -819,44 +819,62 @@ fn stats_test_trust_level0_migration() { ); } - #[test] fn stats_test_trust_level_up() { let mut th = TestHarness::new_buckets(10, 10); - println!("\n-------------Trust Level0 Migration----------------\n"); + println!("\n---Trust Promotion + Migration to Level 1: 30 days----\n"); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); let mut req_t_size: Vec = Vec::new(); let mut resp_t_size: Vec = Vec::new(); let mut resp_handle_t_size: Vec = Vec::new(); - let mut tot_req_size: Vec = Vec::new(); - let mut tot_resp_size: Vec = Vec::new(); - let mut tot_req_t_size: Vec = Vec::new(); - let mut tot_resp_t_size: Vec = Vec::new(); - let mut tot_resp_handle_t_size: Vec = Vec::new(); + let mut sec_req_size: Vec = Vec::new(); + let mut sec_resp_size: Vec = Vec::new(); + let mut sec_req_t_size: Vec = Vec::new(); + let mut sec_resp_t_size: Vec = Vec::new(); + let mut sec_resp_handle_t_size: Vec = Vec::new(); + let mut three_req_size: Vec = Vec::new(); + let mut three_resp_size: Vec = Vec::new(); + let mut three_req_t_size: Vec = Vec::new(); + let mut three_resp_t_size: Vec = Vec::new(); + let mut three_resp_handle_t_size: Vec = Vec::new(); + let mut four_req_size: Vec = Vec::new(); + let mut four_resp_size: Vec = Vec::new(); + let mut four_req_t_size: Vec = Vec::new(); + let mut four_resp_t_size: Vec = Vec::new(); + let mut four_resp_handle_t_size: Vec = Vec::new(); for _ in 0..1000 { let cred = th.open_invite().1 .0; - th.advance_days(47); + th.advance_days(30); let (tp_perf_stat, migcred) = th.trust_promotion(&cred); let (perf_stat, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(20); - let (two_perf_stat, cred2) = th.level_up(&cred1); - th.advance_days(30); + th.advance_days(14); + let (sec_perf_stat, cred2) = th.level_up(&cred1); + th.advance_days(28); let (three_perf_stat, cred3) = th.level_up(&cred2); - th.advance_days(60); - let (four_perf_stat, cred3) = th.level_up(&cred2); - req_size.push(perf_stat.req_len as f64); - req_t_size.push(perf_stat.req_t.as_secs_f64()); - resp_size.push(perf_stat.resp_len as f64); - resp_t_size.push(perf_stat.resp_t.as_secs_f64()); - resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); - tot_req_size.push((perf_stat.req_len + tp_perf_stat.req_len) as f64); - tot_req_t_size.push((perf_stat.req_t + tp_perf_stat.req_t).as_secs_f64()); - tot_resp_size.push((perf_stat.resp_len + tp_perf_stat.resp_len) as f64); - tot_resp_t_size.push((perf_stat.resp_t + tp_perf_stat.resp_t).as_secs_f64()); - tot_resp_handle_t_size - .push((perf_stat.resp_handle_t + tp_perf_stat.resp_handle_t).as_secs_f64()); + th.advance_days(56); + let (four_perf_stat, _) = th.level_up(&cred3); + req_size.push((perf_stat.req_len + tp_perf_stat.req_len) as f64); + req_t_size.push((perf_stat.req_t + tp_perf_stat.req_t).as_secs_f64()); + resp_size.push((perf_stat.resp_len + tp_perf_stat.resp_len) as f64); + resp_t_size.push((perf_stat.resp_t + tp_perf_stat.resp_t).as_secs_f64()); + resp_handle_t_size.push((perf_stat.resp_handle_t + tp_perf_stat.resp_handle_t).as_secs_f64()); + sec_req_size.push(sec_perf_stat.req_len as f64); + sec_req_t_size.push(sec_perf_stat.req_t.as_secs_f64()); + sec_resp_size.push(sec_perf_stat.resp_len as f64); + sec_resp_t_size.push(sec_perf_stat.resp_t.as_secs_f64()); + sec_resp_handle_t_size.push(sec_perf_stat.resp_handle_t.as_secs_f64()); + three_req_size.push(three_perf_stat.req_len as f64); + three_req_t_size.push(three_perf_stat.req_t.as_secs_f64()); + three_resp_size.push(three_perf_stat.resp_len as f64); + three_resp_t_size.push(three_perf_stat.resp_t.as_secs_f64()); + three_resp_handle_t_size.push(three_perf_stat.resp_handle_t.as_secs_f64()); + four_req_size.push(four_perf_stat.req_len as f64); + four_req_t_size.push(four_perf_stat.req_t.as_secs_f64()); + four_resp_size.push(four_perf_stat.resp_len as f64); + four_resp_t_size.push(four_perf_stat.resp_t.as_secs_f64()); + four_resp_handle_t_size.push(four_perf_stat.resp_handle_t.as_secs_f64()); } print_stats_test_results( @@ -867,14 +885,144 @@ fn stats_test_trust_level_up() { resp_handle_t_size, ); - println!("\n-------Total Trust Promotion to Level 1-------\n"); + println!("\n-------Trust Promotion to Level 2: 44 days-------\n"); print_stats_test_results( - tot_req_size, - tot_req_t_size, - tot_resp_size, - tot_resp_t_size, - tot_resp_handle_t_size, + sec_req_size, + sec_req_t_size, + sec_resp_size, + sec_resp_t_size, + sec_resp_handle_t_size, ); + + println!("\n-------Trust Promotion to Level 3: 72 days------\n"); + print_stats_test_results( + three_req_size, + three_req_t_size, + three_resp_size, + three_resp_t_size, + three_resp_handle_t_size, + ); + + println!("\n-------Trust Promotion to Level 4: 128 days------\n"); + print_stats_test_results( + four_req_size, + four_req_t_size, + four_resp_size, + four_resp_t_size, + four_resp_handle_t_size, + ); +} + +#[test] +fn stats_test_invitations() { + let mut th = TestHarness::new_buckets(10, 10); + + println!("\n---------------Issue Invitation----------------\n"); + let mut req_size: Vec = Vec::new(); + let mut resp_size: Vec = Vec::new(); + let mut req_t_size: Vec = Vec::new(); + let mut resp_t_size: Vec = Vec::new(); + let mut resp_handle_t_size: Vec = Vec::new(); + let mut red_req_size: Vec = Vec::new(); + let mut red_resp_size: Vec = Vec::new(); + let mut red_req_t_size: Vec = Vec::new(); + let mut red_resp_t_size: Vec = Vec::new(); + let mut red_resp_handle_t_size: Vec = Vec::new(); + for _ in 0..1000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + th.advance_days(28); + let (perf_stat, (cred2a, invite)) = th.issue_invite(&cred2); + let (bob_perf_stat, bob_cred) = th.redeem_invite(&invite); + req_size.push(perf_stat.req_len as f64); + req_t_size.push(perf_stat.req_t.as_secs_f64()); + resp_size.push(perf_stat.resp_len as f64); + resp_t_size.push(perf_stat.resp_t.as_secs_f64()); + resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); + red_req_size.push(bob_perf_stat.req_len as f64); + red_req_t_size.push(bob_perf_stat.req_t.as_secs_f64()); + red_resp_size.push(bob_perf_stat.resp_len as f64); + red_resp_t_size.push(bob_perf_stat.resp_t.as_secs_f64()); + red_resp_handle_t_size.push(bob_perf_stat.resp_handle_t.as_secs_f64()); + } + + print_stats_test_results( + req_size, + req_t_size, + resp_size, + resp_t_size, + resp_handle_t_size, + ); + + println!("\n---------------Redeem Invitation----------------\n"); + print_stats_test_results( + red_req_size, + red_req_t_size, + red_resp_size, + red_resp_t_size, + red_resp_handle_t_size, + ); + +} + +#[test] +fn stats_test_blockage migration() { + let mut th = TestHarness::new_buckets(10, 10); + + println!("\n---------------Blockage Migration----------------\n"); + let mut req_size: Vec = Vec::new(); + let mut resp_size: Vec = Vec::new(); + let mut req_t_size: Vec = Vec::new(); + let mut resp_t_size: Vec = Vec::new(); + let mut resp_handle_t_size: Vec = Vec::new(); + let mut red_req_size: Vec = Vec::new(); + let mut red_resp_size: Vec = Vec::new(); + let mut red_req_t_size: Vec = Vec::new(); + let mut red_resp_t_size: Vec = Vec::new(); + let mut red_resp_handle_t_size: Vec = Vec::new(); + for _ in 0..1000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + th.advance_days(28); + let (perf_stat, (cred2a, invite)) = th.issue_invite(&cred2); + let (bob_perf_stat, bob_cred) = th.redeem_invite(&invite); + req_size.push(perf_stat.req_len as f64); + req_t_size.push(perf_stat.req_t.as_secs_f64()); + resp_size.push(perf_stat.resp_len as f64); + resp_t_size.push(perf_stat.resp_t.as_secs_f64()); + resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); + red_req_size.push(bob_perf_stat.req_len as f64); + red_req_t_size.push(bob_perf_stat.req_t.as_secs_f64()); + red_resp_size.push(bob_perf_stat.resp_len as f64); + red_resp_t_size.push(bob_perf_stat.resp_t.as_secs_f64()); + red_resp_handle_t_size.push(bob_perf_stat.resp_handle_t.as_secs_f64()); + } + + print_stats_test_results( + req_size, + req_t_size, + resp_size, + resp_t_size, + resp_handle_t_size, + ); + + println!("\n---------------Redeem Invitation----------------\n"); + print_stats_test_results( + red_req_size, + red_req_t_size, + red_resp_size, + red_resp_t_size, + red_resp_handle_t_size, + ); + } #[test] fn stats_test_blocked_bridges() { From ea8ac7eb9c98e8d058ae40276e56f333420c24c6 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Fri, 25 Jun 2021 01:49:58 -0400 Subject: [PATCH 062/115] Add blockage migration stats test --- crates/lox-library/src/tests.rs | 101 +++++++------------------------- 1 file changed, 22 insertions(+), 79 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 32615a6..a98f92f 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -859,7 +859,8 @@ fn stats_test_trust_level_up() { req_t_size.push((perf_stat.req_t + tp_perf_stat.req_t).as_secs_f64()); resp_size.push((perf_stat.resp_len + tp_perf_stat.resp_len) as f64); resp_t_size.push((perf_stat.resp_t + tp_perf_stat.resp_t).as_secs_f64()); - resp_handle_t_size.push((perf_stat.resp_handle_t + tp_perf_stat.resp_handle_t).as_secs_f64()); + resp_handle_t_size + .push((perf_stat.resp_handle_t + tp_perf_stat.resp_handle_t).as_secs_f64()); sec_req_size.push(sec_perf_stat.req_len as f64); sec_req_t_size.push(sec_perf_stat.req_t.as_secs_f64()); sec_resp_size.push(sec_perf_stat.resp_len as f64); @@ -966,14 +967,11 @@ fn stats_test_invitations() { red_resp_t_size, red_resp_handle_t_size, ); - } #[test] -fn stats_test_blockage migration() { - let mut th = TestHarness::new_buckets(10, 10); - - println!("\n---------------Blockage Migration----------------\n"); +fn stats_test_blockage_migration() { + println!("\n---------------Check Blockage----------------\n"); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); let mut req_t_size: Vec = Vec::new(); @@ -985,6 +983,7 @@ fn stats_test_blockage migration() { let mut red_resp_t_size: Vec = Vec::new(); let mut red_resp_handle_t_size: Vec = Vec::new(); for _ in 0..1000 { + let mut th = TestHarness::new_buckets(3, 3); let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -992,18 +991,27 @@ fn stats_test_blockage migration() { th.advance_days(14); let (_, cred2) = th.level_up(&cred1); th.advance_days(28); - let (perf_stat, (cred2a, invite)) = th.issue_invite(&cred2); - let (bob_perf_stat, bob_cred) = th.redeem_invite(&invite); + let (_, cred3) = th.level_up(&cred2); + let (id, key) = bridge_table::from_scalar(cred3.bucket).unwrap(); + let encbuckets = th.ba.enc_bridge_table(); + let bucket = + bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); + th.ba.bridge_unreachable(&bucket.0[0], &mut th.bdb); + th.ba.bridge_unreachable(&bucket.0[1], &mut th.bdb); + th.ba.bridge_unreachable(&bucket.0[2], &mut th.bdb); + let (perf_stat, migration) = th.check_blockage(&cred3); + let (block_perf_stat, cred4) = th.blockage_migration(&cred3, &migration); + req_size.push(perf_stat.req_len as f64); req_t_size.push(perf_stat.req_t.as_secs_f64()); resp_size.push(perf_stat.resp_len as f64); resp_t_size.push(perf_stat.resp_t.as_secs_f64()); resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); - red_req_size.push(bob_perf_stat.req_len as f64); - red_req_t_size.push(bob_perf_stat.req_t.as_secs_f64()); - red_resp_size.push(bob_perf_stat.resp_len as f64); - red_resp_t_size.push(bob_perf_stat.resp_t.as_secs_f64()); - red_resp_handle_t_size.push(bob_perf_stat.resp_handle_t.as_secs_f64()); + red_req_size.push(block_perf_stat.req_len as f64); + red_req_t_size.push(block_perf_stat.req_t.as_secs_f64()); + red_resp_size.push(block_perf_stat.resp_len as f64); + red_resp_t_size.push(block_perf_stat.resp_t.as_secs_f64()); + red_resp_handle_t_size.push(block_perf_stat.resp_handle_t.as_secs_f64()); } print_stats_test_results( @@ -1014,7 +1022,7 @@ fn stats_test_blockage migration() { resp_handle_t_size, ); - println!("\n---------------Redeem Invitation----------------\n"); + println!("\n---------------Blockage Migration----------------\n"); print_stats_test_results( red_req_size, red_req_t_size, @@ -1022,71 +1030,6 @@ fn stats_test_blockage migration() { red_resp_t_size, red_resp_handle_t_size, ); - -} -#[test] -fn stats_test_blocked_bridges() { - let mut th = TestHarness::new_buckets(10, 10); - println!("\n-------Trust Promotion With Blocked Bridges--------\n"); - - let mut req_size_b: Vec = Vec::new(); - let mut resp_size_b: Vec = Vec::new(); - let mut req_t_size_b: Vec = Vec::new(); - let mut resp_t_size_b: Vec = Vec::new(); - let mut resp_handle_t_size_b: Vec = Vec::new(); - for _ in 0..1000 { - let cred = th.open_invite().1 .0; - th.advance_days(47); - let (perf_stat, migcred) = th.trust_promotion(&cred); - req_size_b.push(perf_stat.req_len as f64); - req_t_size_b.push(perf_stat.req_t.as_secs_f64()); - resp_size_b.push(perf_stat.resp_len as f64); - resp_t_size_b.push(perf_stat.resp_t.as_secs_f64()); - resp_handle_t_size_b.push(perf_stat.resp_handle_t.as_secs_f64()); - } - - // Mark 5 bridges in untrusted buckets as unreachable - for i in 0..50 { - if i % 2 == 0 { - let b0 = th.ba.bridge_table.buckets[i][0]; - th.ba.bridge_unreachable(&b0, &mut th.bdb); - } - } - - print_stats_test_results( - req_size_b, - req_t_size_b, - resp_size_b, - resp_t_size_b, - resp_handle_t_size_b, - ); -} - -#[test] -fn stats_test_something_else_test() { - let mut th = TestHarness::new_buckets(10, 10); - println!("\n---------------Block Bridges-------------------\n"); - - let mut req_size2: Vec = Vec::new(); - let mut resp_size2: Vec = Vec::new(); - let mut req_t_size2: Vec = Vec::new(); - let mut resp_t_size2: Vec = Vec::new(); - let mut resp_handle_t_size2: Vec = Vec::new(); - for _ in 0..1000 { - let (perf_stat2, _) = th.open_invite(); - req_size2.push(perf_stat2.req_len as f64); - req_t_size2.push(perf_stat2.req_t.as_secs_f64()); - resp_size2.push(perf_stat2.resp_len as f64); - resp_t_size2.push(perf_stat2.resp_t.as_secs_f64()); - resp_handle_t_size2.push(perf_stat2.resp_handle_t.as_secs_f64()); - } - print_stats_test_results( - req_size2, - req_t_size2, - resp_size2, - resp_t_size2, - resp_handle_t_size2, - ); } fn print_test_results(perf_stat: PerfStat) { From 7dedf2ab471c09bfedb5cdc7b0c102d230d10697 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 30 Jun 2021 13:39:15 -0400 Subject: [PATCH 063/115] Updated print statements and number of users --- crates/lox-library/src/tests.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index a98f92f..1895a7f 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -714,13 +714,12 @@ fn test_blockage_migration() { fn stats_test_open_invite() { let mut th = TestHarness::new_buckets(10, 10); - println!("\n---------------Open Invitationn-------------------\n"); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); let mut req_t_size: Vec = Vec::new(); let mut resp_t_size: Vec = Vec::new(); let mut resp_handle_t_size: Vec = Vec::new(); - for _ in 0..1000 { + for _ in 0..10000 { let (perf_stat, _) = th.open_invite(); req_size.push(perf_stat.req_len as f64); req_t_size.push(perf_stat.req_t.as_secs_f64()); @@ -729,6 +728,7 @@ fn stats_test_open_invite() { resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); } + println!("\n---------------Open Invitationn-------------------\n"); print_stats_test_results( req_size, req_t_size, @@ -741,14 +741,13 @@ fn stats_test_open_invite() { #[test] fn stats_test_trust_promotion() { let mut th = TestHarness::new_buckets(10, 10); - println!("\n-------Trust Promotion--------\n"); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); let mut req_t_size: Vec = Vec::new(); let mut resp_t_size: Vec = Vec::new(); let mut resp_handle_t_size: Vec = Vec::new(); - for _ in 0..1000 { + for _ in 0..10000 { let cred = th.open_invite().1 .0; th.advance_days(47); let (perf_stat, _) = th.trust_promotion(&cred); @@ -759,6 +758,7 @@ fn stats_test_trust_promotion() { resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); } + println!("\n-------Trust Promotion--------\n"); print_stats_test_results( req_size, req_t_size, @@ -772,7 +772,6 @@ fn stats_test_trust_promotion() { fn stats_test_trust_level0_migration() { let mut th = TestHarness::new_buckets(10, 10); - println!("\n-------------Trust Level0 Migration----------------\n"); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); let mut req_t_size: Vec = Vec::new(); @@ -783,7 +782,7 @@ fn stats_test_trust_level0_migration() { let mut tot_req_t_size: Vec = Vec::new(); let mut tot_resp_t_size: Vec = Vec::new(); let mut tot_resp_handle_t_size: Vec = Vec::new(); - for _ in 0..1000 { + for _ in 0..10000 { let cred = th.open_invite().1 .0; th.advance_days(47); let (tp_perf_stat, migcred) = th.trust_promotion(&cred); @@ -801,6 +800,7 @@ fn stats_test_trust_level0_migration() { .push((perf_stat.resp_handle_t + tp_perf_stat.resp_handle_t).as_secs_f64()); } + println!("\n-------------Trust Level0 Migration----------------\n"); print_stats_test_results( req_size, req_t_size, @@ -823,7 +823,6 @@ fn stats_test_trust_level0_migration() { fn stats_test_trust_level_up() { let mut th = TestHarness::new_buckets(10, 10); - println!("\n---Trust Promotion + Migration to Level 1: 30 days----\n"); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); let mut req_t_size: Vec = Vec::new(); @@ -844,7 +843,7 @@ fn stats_test_trust_level_up() { let mut four_req_t_size: Vec = Vec::new(); let mut four_resp_t_size: Vec = Vec::new(); let mut four_resp_handle_t_size: Vec = Vec::new(); - for _ in 0..1000 { + for _ in 0..10000 { let cred = th.open_invite().1 .0; th.advance_days(30); let (tp_perf_stat, migcred) = th.trust_promotion(&cred); @@ -878,6 +877,7 @@ fn stats_test_trust_level_up() { four_resp_handle_t_size.push(four_perf_stat.resp_handle_t.as_secs_f64()); } + println!("\n---Trust Promotion + Migration to Level 1: 30 days----\n"); print_stats_test_results( req_size, req_t_size, @@ -918,7 +918,6 @@ fn stats_test_trust_level_up() { fn stats_test_invitations() { let mut th = TestHarness::new_buckets(10, 10); - println!("\n---------------Issue Invitation----------------\n"); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); let mut req_t_size: Vec = Vec::new(); @@ -929,7 +928,7 @@ fn stats_test_invitations() { let mut red_req_t_size: Vec = Vec::new(); let mut red_resp_t_size: Vec = Vec::new(); let mut red_resp_handle_t_size: Vec = Vec::new(); - for _ in 0..1000 { + for _ in 0..10000 { let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -951,6 +950,7 @@ fn stats_test_invitations() { red_resp_handle_t_size.push(bob_perf_stat.resp_handle_t.as_secs_f64()); } + println!("\n---------------Issue Invitation----------------\n"); print_stats_test_results( req_size, req_t_size, @@ -971,7 +971,6 @@ fn stats_test_invitations() { #[test] fn stats_test_blockage_migration() { - println!("\n---------------Check Blockage----------------\n"); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); let mut req_t_size: Vec = Vec::new(); @@ -982,7 +981,7 @@ fn stats_test_blockage_migration() { let mut red_req_t_size: Vec = Vec::new(); let mut red_resp_t_size: Vec = Vec::new(); let mut red_resp_handle_t_size: Vec = Vec::new(); - for _ in 0..1000 { + for _ in 0..10000 { let mut th = TestHarness::new_buckets(3, 3); let cred = th.open_invite().1 .0; th.advance_days(30); @@ -1014,6 +1013,7 @@ fn stats_test_blockage_migration() { red_resp_handle_t_size.push(block_perf_stat.resp_handle_t.as_secs_f64()); } + println!("\n---------------Check Blockage----------------\n"); print_stats_test_results( req_size, req_t_size, From c69e740366b1e5b8c84aa9a1f574967de57cd08e Mon Sep 17 00:00:00 2001 From: onyinyang Date: Tue, 6 Jul 2021 18:08:52 -0400 Subject: [PATCH 064/115] Add tests for varying percentages of blocked bridge --- crates/lox-library/src/tests.rs | 295 +++++++++++++++++++++++++++----- 1 file changed, 248 insertions(+), 47 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 1895a7f..e218426 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -4,7 +4,9 @@ BridgeLine::random() or private fields */ use super::bridge_table::BridgeLine; use super::proto::*; use super::*; +use rand::Rng; use statistical::{mean, standard_deviation}; +use std::collections::HashSet; use std::time::{Duration, Instant}; struct PerfStat { @@ -84,7 +86,7 @@ impl TestHarness { open_invite::handle_response(state, decode_resp, &self.ba.lox_pub).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); - return ( + ( PerfStat { req_len, resp_len, @@ -93,7 +95,7 @@ impl TestHarness { resp_handle_t, }, (cred, bridgeline), - ); + ) } fn trust_promotion(&mut self, cred: &cred::Lox) -> (PerfStat, cred::Migration) { @@ -116,7 +118,7 @@ impl TestHarness { let migcred = trust_promotion::handle_response(promstate, decode_resp).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); - return ( + ( PerfStat { req_len, resp_len, @@ -125,7 +127,7 @@ impl TestHarness { resp_handle_t, }, migcred, - ); + ) } fn level0_migration( @@ -152,7 +154,7 @@ impl TestHarness { let cred = migration::handle_response(migstate, decode_resp, &self.ba.lox_pub).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); - return ( + ( PerfStat { req_len, resp_len, @@ -161,7 +163,7 @@ impl TestHarness { resp_handle_t, }, cred, - ); + ) } fn level_up(&mut self, cred: &cred::Lox) -> (PerfStat, cred::Lox) { @@ -201,7 +203,7 @@ impl TestHarness { let cred = level_up::handle_response(state, decode_resp, &self.ba.lox_pub).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); - return ( + ( PerfStat { req_len, resp_len, @@ -210,7 +212,7 @@ impl TestHarness { resp_handle_t, }, cred, - ); + ) } fn issue_invite(&mut self, cred: &cred::Lox) -> (PerfStat, (cred::Lox, cred::Invitation)) { @@ -253,7 +255,7 @@ impl TestHarness { .unwrap(); let resp_handle_t = resp_handle_start.elapsed(); - return ( + ( PerfStat { req_len, resp_len, @@ -262,7 +264,7 @@ impl TestHarness { resp_handle_t, }, (cred, invite), - ); + ) } fn redeem_invite(&mut self, inv: &cred::Invitation) -> (PerfStat, cred::Lox) { @@ -285,7 +287,7 @@ impl TestHarness { let cred = redeem_invite::handle_response(state, decode_resp, &self.ba.lox_pub).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); - return ( + ( PerfStat { req_len, resp_len, @@ -294,7 +296,7 @@ impl TestHarness { resp_handle_t, }, cred, - ); + ) } fn check_blockage(&mut self, cred: &cred::Lox) -> (PerfStat, cred::Migration) { @@ -316,7 +318,7 @@ impl TestHarness { let migcred = check_blockage::handle_response(state, decode_resp).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); - return ( + ( PerfStat { req_len, resp_len, @@ -325,7 +327,7 @@ impl TestHarness { resp_handle_t, }, migcred, - ); + ) } fn blockage_migration( @@ -355,7 +357,7 @@ impl TestHarness { blockage_migration::handle_response(state, decode_resp, &self.ba.lox_pub).unwrap(); let resp_handle_t = resp_handle_start.elapsed(); - return ( + ( PerfStat { req_len, resp_len, @@ -364,7 +366,7 @@ impl TestHarness { resp_handle_t, }, cred, - ); + ) } } @@ -936,8 +938,8 @@ fn stats_test_invitations() { th.advance_days(14); let (_, cred2) = th.level_up(&cred1); th.advance_days(28); - let (perf_stat, (cred2a, invite)) = th.issue_invite(&cred2); - let (bob_perf_stat, bob_cred) = th.redeem_invite(&invite); + let (perf_stat, (_, invite)) = th.issue_invite(&cred2); + let (bob_perf_stat, _) = th.redeem_invite(&invite); req_size.push(perf_stat.req_len as f64); req_t_size.push(perf_stat.req_t.as_secs_f64()); resp_size.push(perf_stat.resp_len as f64); @@ -970,7 +972,203 @@ fn stats_test_invitations() { } #[test] -fn stats_test_blockage_migration() { +fn stats_test_blockage_migration_5() { + let mut th = TestHarness::new_buckets(10, 10); + let mut credentials: Vec = Vec::new(); + for _ in 0..1000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 5, credentials); +} + +#[test] +fn stats_test_blockage_migration_10() { + let mut th = TestHarness::new_buckets(10, 10); + let mut credentials: Vec = Vec::new(); + for _ in 0..1000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 10, credentials); +} + +#[test] +fn stats_test_blockage_migration_15() { + let mut th = TestHarness::new_buckets(10, 10); + let mut credentials: Vec = Vec::new(); + for _ in 0..100 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 15, credentials); +} + +#[test] +fn stats_test_blockage_migration_20() { + let mut th = TestHarness::new_buckets(10, 10); + let mut credentials: Vec = Vec::new(); + for _ in 0..100 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 20, credentials); +} + +#[test] +fn stats_test_blockage_migration_25() { + let mut th = TestHarness::new_buckets(10, 10); + let mut credentials: Vec = Vec::new(); + for _ in 0..100 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 25, credentials); +} + +#[test] +fn stats_test_blockage_migration_30() { + let mut th = TestHarness::new_buckets(10, 10); + let mut credentials: Vec = Vec::new(); + for _ in 0..100 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 30, credentials); +} + +#[test] +fn stats_test_blockage_migration_35() { + let mut th = TestHarness::new_buckets(10, 10); + let mut credentials: Vec = Vec::new(); + for _ in 0..100 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 35, credentials); +} + +#[test] +fn stats_test_blockage_migration_40() { + let mut th = TestHarness::new_buckets(10, 10); + let mut credentials: Vec = Vec::new(); + for _ in 0..100 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 40, credentials); +} + +/// Blocks a percentage of the total number of bridges for the passed Test Harness +/// for the number of buckets and hot spares passed at initialization + +fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec) { + let to_block: usize = (th.ba.bridge_table.buckets.len() * percentage / 100).into(); + let mut block_index: HashSet = HashSet::new(); + let mut rng = rand::thread_rng(); + + while block_index.len() <= to_block - 1 { + let rand_num = rng.gen_range(0, th.ba.bridge_table.buckets.len()); + block_index.insert(rand_num); + } + + for index in block_index { + let b0 = th.ba.bridge_table.buckets[index][0]; + let b1 = th.ba.bridge_table.buckets[index][1]; + let b2 = th.ba.bridge_table.buckets[index][2]; + th.ba.bridge_unreachable(&b0, &mut th.bdb); + th.ba.bridge_unreachable(&b1, &mut th.bdb); + th.ba.bridge_unreachable(&b2, &mut th.bdb); + } + let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); let mut req_t_size: Vec = Vec::new(); @@ -981,39 +1179,39 @@ fn stats_test_blockage_migration() { let mut red_req_t_size: Vec = Vec::new(); let mut red_resp_t_size: Vec = Vec::new(); let mut red_resp_handle_t_size: Vec = Vec::new(); - for _ in 0..10000 { - let mut th = TestHarness::new_buckets(3, 3); - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - th.advance_days(28); - let (_, cred3) = th.level_up(&cred2); - let (id, key) = bridge_table::from_scalar(cred3.bucket).unwrap(); + for cred in credentials { + let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); let encbuckets = th.ba.enc_bridge_table(); let bucket = bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); - th.ba.bridge_unreachable(&bucket.0[0], &mut th.bdb); - th.ba.bridge_unreachable(&bucket.0[1], &mut th.bdb); - th.ba.bridge_unreachable(&bucket.0[2], &mut th.bdb); - let (perf_stat, migration) = th.check_blockage(&cred3); - let (block_perf_stat, cred4) = th.blockage_migration(&cred3, &migration); - req_size.push(perf_stat.req_len as f64); - req_t_size.push(perf_stat.req_t.as_secs_f64()); - resp_size.push(perf_stat.resp_len as f64); - resp_t_size.push(perf_stat.resp_t.as_secs_f64()); - resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); - red_req_size.push(block_perf_stat.req_len as f64); - red_req_t_size.push(block_perf_stat.req_t.as_secs_f64()); - red_resp_size.push(block_perf_stat.resp_len as f64); - red_resp_t_size.push(block_perf_stat.resp_t.as_secs_f64()); - red_resp_handle_t_size.push(block_perf_stat.resp_handle_t.as_secs_f64()); + let mut count = 0; + for bridge_line in &bucket.0 { + if th.ba.bridge_table.reachable.contains_key(bridge_line) { + count = count + 1; + } + } + + if count < 2 { + let (perf_stat, migration) = th.check_blockage(&cred); + let (block_perf_stat, _) = th.blockage_migration(&cred, &migration); + req_size.push(perf_stat.req_len as f64); + req_t_size.push(perf_stat.req_t.as_secs_f64()); + resp_size.push(perf_stat.resp_len as f64); + resp_t_size.push(perf_stat.resp_t.as_secs_f64()); + resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); + red_req_size.push(block_perf_stat.req_len as f64); + red_req_t_size.push(block_perf_stat.req_t.as_secs_f64()); + red_resp_size.push(block_perf_stat.resp_len as f64); + red_resp_t_size.push(block_perf_stat.resp_t.as_secs_f64()); + red_resp_handle_t_size.push(block_perf_stat.resp_handle_t.as_secs_f64()); + } } - println!("\n---------------Check Blockage----------------\n"); + println!( + "\n---------------Check Blockage {}---------------\n", + percentage + ); print_stats_test_results( req_size, req_t_size, @@ -1022,7 +1220,10 @@ fn stats_test_blockage_migration() { resp_handle_t_size, ); - println!("\n---------------Blockage Migration----------------\n"); + println!( + "\n---------------Blockage Migration {}---------------\n", + percentage + ); print_stats_test_results( red_req_size, red_req_t_size, From a00d97dfe908b8ffba377763d3f4f66a30e0ad20 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Tue, 6 Jul 2021 19:05:45 -0400 Subject: [PATCH 065/115] Corrected error causing response handling stdev anomaly, adjusted test size for blockages --- crates/lox-library/src/tests.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index e218426..854149f 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -973,7 +973,7 @@ fn stats_test_invitations() { #[test] fn stats_test_blockage_migration_5() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(15, 15); let mut credentials: Vec = Vec::new(); for _ in 0..1000 { let cred = th.open_invite().1 .0; @@ -995,7 +995,7 @@ fn stats_test_blockage_migration_5() { #[test] fn stats_test_blockage_migration_10() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(15, 15); let mut credentials: Vec = Vec::new(); for _ in 0..1000 { let cred = th.open_invite().1 .0; @@ -1017,9 +1017,9 @@ fn stats_test_blockage_migration_10() { #[test] fn stats_test_blockage_migration_15() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(15, 15); let mut credentials: Vec = Vec::new(); - for _ in 0..100 { + for _ in 0..10000 { let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1039,9 +1039,9 @@ fn stats_test_blockage_migration_15() { #[test] fn stats_test_blockage_migration_20() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(15, 15); let mut credentials: Vec = Vec::new(); - for _ in 0..100 { + for _ in 0..10000 { let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1061,9 +1061,9 @@ fn stats_test_blockage_migration_20() { #[test] fn stats_test_blockage_migration_25() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(15, 15); let mut credentials: Vec = Vec::new(); - for _ in 0..100 { + for _ in 0..10000 { let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1083,9 +1083,9 @@ fn stats_test_blockage_migration_25() { #[test] fn stats_test_blockage_migration_30() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(15, 15); let mut credentials: Vec = Vec::new(); - for _ in 0..100 { + for _ in 0..10000 { let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1105,9 +1105,9 @@ fn stats_test_blockage_migration_30() { #[test] fn stats_test_blockage_migration_35() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(15, 15); let mut credentials: Vec = Vec::new(); - for _ in 0..100 { + for _ in 0..10000 { let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1127,9 +1127,9 @@ fn stats_test_blockage_migration_35() { #[test] fn stats_test_blockage_migration_40() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(15, 15); let mut credentials: Vec = Vec::new(); - for _ in 0..100 { + for _ in 0..10000 { let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1256,7 +1256,7 @@ fn print_stats_test_results( let resp_std_dev = standard_deviation(&resp_size, Some(mean_resp_size)); let mean_resp_t_size = mean(&resp_t_size); let resp_t_std_dev = standard_deviation(&resp_t_size, Some(mean_resp_t_size)); - let mean_resp_handle_t_size = mean(&resp_t_size); + let mean_resp_handle_t_size = mean(&resp_handle_t_size); let resp_handle_t_std_dev = standard_deviation(&resp_handle_t_size, Some(mean_resp_handle_t_size)); From bc5a1e5c0da5e44e9e0201fe3129a144f5b4ae4a Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 7 Jul 2021 15:28:17 +0000 Subject: [PATCH 066/115] Add more bridges for consistency, printout units Committer: ltulloch --- crates/lox-library/src/tests.rs | 50 ++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 854149f..649f0ed 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -714,7 +714,7 @@ fn test_blockage_migration() { #[test] fn stats_test_open_invite() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(150, 150); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); @@ -742,7 +742,7 @@ fn stats_test_open_invite() { #[test] fn stats_test_trust_promotion() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(150, 150); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); @@ -772,7 +772,7 @@ fn stats_test_trust_promotion() { #[test] fn stats_test_trust_level0_migration() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(150, 150); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); @@ -823,7 +823,7 @@ fn stats_test_trust_level0_migration() { #[test] fn stats_test_trust_level_up() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(150, 150); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); @@ -918,7 +918,7 @@ fn stats_test_trust_level_up() { #[test] fn stats_test_invitations() { - let mut th = TestHarness::new_buckets(10, 10); + let mut th = TestHarness::new_buckets(150, 150); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); @@ -973,7 +973,7 @@ fn stats_test_invitations() { #[test] fn stats_test_blockage_migration_5() { - let mut th = TestHarness::new_buckets(15, 15); + let mut th = TestHarness::new_buckets(150, 150); let mut credentials: Vec = Vec::new(); for _ in 0..1000 { let cred = th.open_invite().1 .0; @@ -995,7 +995,7 @@ fn stats_test_blockage_migration_5() { #[test] fn stats_test_blockage_migration_10() { - let mut th = TestHarness::new_buckets(15, 15); + let mut th = TestHarness::new_buckets(150, 150); let mut credentials: Vec = Vec::new(); for _ in 0..1000 { let cred = th.open_invite().1 .0; @@ -1017,7 +1017,7 @@ fn stats_test_blockage_migration_10() { #[test] fn stats_test_blockage_migration_15() { - let mut th = TestHarness::new_buckets(15, 15); + let mut th = TestHarness::new_buckets(150, 150); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1039,7 +1039,7 @@ fn stats_test_blockage_migration_15() { #[test] fn stats_test_blockage_migration_20() { - let mut th = TestHarness::new_buckets(15, 15); + let mut th = TestHarness::new_buckets(150, 150); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1061,7 +1061,7 @@ fn stats_test_blockage_migration_20() { #[test] fn stats_test_blockage_migration_25() { - let mut th = TestHarness::new_buckets(15, 15); + let mut th = TestHarness::new_buckets(150, 150); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1083,7 +1083,7 @@ fn stats_test_blockage_migration_25() { #[test] fn stats_test_blockage_migration_30() { - let mut th = TestHarness::new_buckets(15, 15); + let mut th = TestHarness::new_buckets(150, 150); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1105,7 +1105,7 @@ fn stats_test_blockage_migration_30() { #[test] fn stats_test_blockage_migration_35() { - let mut th = TestHarness::new_buckets(15, 15); + let mut th = TestHarness::new_buckets(150, 150); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1127,7 +1127,7 @@ fn stats_test_blockage_migration_35() { #[test] fn stats_test_blockage_migration_40() { - let mut th = TestHarness::new_buckets(15, 15); + let mut th = TestHarness::new_buckets(150, 150); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1234,9 +1234,9 @@ fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec Date: Sun, 18 Jul 2021 18:51:49 -0400 Subject: [PATCH 067/115] Changed blockage test to only block non-spare buckets --- crates/lox-library/src/tests.rs | 251 +++++++++++++++++++++++++++++++- 1 file changed, 248 insertions(+), 3 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 649f0ed..95f197a 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -1147,11 +1147,256 @@ fn stats_test_blockage_migration_40() { block_bridges(&mut th, 40, credentials); } -/// Blocks a percentage of the total number of bridges for the passed Test Harness -/// for the number of buckets and hot spares passed at initialization +#[test] +fn stats_test_blockage_migration_45() { + let mut th = TestHarness::new_buckets(150, 150); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 45, credentials); +} + +#[test] +fn stats_test_blockage_migration_50() { + let mut th = TestHarness::new_buckets(150, 150); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 50, credentials); +} + +#[test] +fn stats_test_blockage_migration_55() { + let mut th = TestHarness::new_buckets(150, 150); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 55, credentials); +} + +#[test] +fn stats_test_blockage_migration_60() { + let mut th = TestHarness::new_buckets(150, 150); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 60, credentials); +} + +#[test] +fn stats_test_blockage_migration_65() { + let mut th = TestHarness::new_buckets(150, 150); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 65, credentials); +} + +#[test] +fn stats_test_blockage_migration_70() { + let mut th = TestHarness::new_buckets(150, 150); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 70, credentials); +} + + +#[test] +fn stats_test_blockage_migration_80() { + let mut th = TestHarness::new_buckets(150, 150); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 80, credentials); +} + +#[test] +fn stats_test_blockage_migration_85() { + let mut th = TestHarness::new_buckets(150, 150); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 85, credentials); +} + +#[test] +fn stats_test_blockage_migration_90() { + let mut th = TestHarness::new_buckets(150, 150); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 90, credentials); +} + +#[test] +fn stats_test_blockage_migration_95() { + let mut th = TestHarness::new_buckets(150, 150); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 95, credentials); +} + +#[test] +fn stats_test_blockage_migration_100() { + let mut th = TestHarness::new_buckets(150, 150); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 100, credentials); +} + +/// Blocks a percentage of the bridges for the passed Test Harness +/// excluding the hot spare buckets as they will not have been handed out. +/// The logic assumes hot spare buckets are appended to the end of the bridge_table +/// bucket list. fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec) { - let to_block: usize = (th.ba.bridge_table.buckets.len() * percentage / 100).into(); + let to_block: usize = ((th.ba.bridge_table.buckets.len() - th.ba.bridge_table.spares.len()) * percentage / 100).into(); let mut block_index: HashSet = HashSet::new(); let mut rng = rand::thread_rng(); From 20511632e82f25450fd74476eb49d4c66af5ff1e Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 19 Jul 2021 15:36:37 +0000 Subject: [PATCH 068/115] Fixed bug that still blocked spares --- crates/lox-library/src/tests.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 95f197a..c541ea1 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -1396,12 +1396,13 @@ fn stats_test_blockage_migration_100() { /// bucket list. fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec) { - let to_block: usize = ((th.ba.bridge_table.buckets.len() - th.ba.bridge_table.spares.len()) * percentage / 100).into(); + let blockable_bridges = th.ba.bridge_table.buckets.len() - th.ba.bridge_table.spares.len(); + let to_block: usize = (blockable_bridges * percentage / 100).into(); let mut block_index: HashSet = HashSet::new(); let mut rng = rand::thread_rng(); while block_index.len() <= to_block - 1 { - let rand_num = rng.gen_range(0, th.ba.bridge_table.buckets.len()); + let rand_num = rng.gen_range(0, blockable_bridges); block_index.insert(rand_num); } From 3d8f1e799e1b924442b3e6584e3fb0a162206172 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 26 Jul 2021 15:12:39 -0400 Subject: [PATCH 069/115] Remove open invitation buckets from blockages, add test for 75% --- crates/lox-library/src/tests.rs | 34 +++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index c541ea1..2ab2e44 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -1279,6 +1279,27 @@ fn stats_test_blockage_migration_70() { block_bridges(&mut th, 70, credentials); } +#[test] +fn stats_test_blockage_migration_75() { + let mut th = TestHarness::new_buckets(150, 150); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + block_bridges(&mut th, 75, credentials); +} #[test] fn stats_test_blockage_migration_80() { @@ -1396,14 +1417,19 @@ fn stats_test_blockage_migration_100() { /// bucket list. fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec) { - let blockable_bridges = th.ba.bridge_table.buckets.len() - th.ba.bridge_table.spares.len(); - let to_block: usize = (blockable_bridges * percentage / 100).into(); + let blockable_num = th.ba.bridge_table.buckets.len() + - th.ba.bridge_table.spares.len() + - th.bdb.openinv_buckets.len(); + let blockable_range = th.ba.bridge_table.buckets.len() - th.ba.bridge_table.spares.len(); + let to_block: usize = (blockable_num * percentage / 100).into(); let mut block_index: HashSet = HashSet::new(); let mut rng = rand::thread_rng(); while block_index.len() <= to_block - 1 { - let rand_num = rng.gen_range(0, blockable_bridges); - block_index.insert(rand_num); + let rand_num = rng.gen_range(0, blockable_range); + if !th.bdb.openinv_buckets.contains(&(rand_num as u32)) { + block_index.insert(rand_num); + } } for index in block_index { From 82272ea933f0ce7659614f0806dda03656f3aadc Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 29 Sep 2021 01:11:12 -0400 Subject: [PATCH 070/115] Added perfstat time outputs for each test --- crates/lox-library/src/tests.rs | 376 ++++++++++++++------------------ 1 file changed, 159 insertions(+), 217 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 2ab2e44..0b21dd3 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -713,206 +713,146 @@ fn test_blockage_migration() { } #[test] -fn stats_test_open_invite() { +fn stats_test_trust_levels() { let mut th = TestHarness::new_buckets(150, 150); - let mut req_size: Vec = Vec::new(); - let mut resp_size: Vec = Vec::new(); - let mut req_t_size: Vec = Vec::new(); - let mut resp_t_size: Vec = Vec::new(); - let mut resp_handle_t_size: Vec = Vec::new(); - for _ in 0..10000 { - let (perf_stat, _) = th.open_invite(); - req_size.push(perf_stat.req_len as f64); - req_t_size.push(perf_stat.req_t.as_secs_f64()); - resp_size.push(perf_stat.resp_len as f64); - resp_t_size.push(perf_stat.resp_t.as_secs_f64()); - resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); - } - - println!("\n---------------Open Invitationn-------------------\n"); - print_stats_test_results( - req_size, - req_t_size, - resp_size, - resp_t_size, - resp_handle_t_size, - ); -} - -#[test] -fn stats_test_trust_promotion() { - let mut th = TestHarness::new_buckets(150, 150); - - let mut req_size: Vec = Vec::new(); - let mut resp_size: Vec = Vec::new(); - let mut req_t_size: Vec = Vec::new(); - let mut resp_t_size: Vec = Vec::new(); - let mut resp_handle_t_size: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(47); - let (perf_stat, _) = th.trust_promotion(&cred); - req_size.push(perf_stat.req_len as f64); - req_t_size.push(perf_stat.req_t.as_secs_f64()); - resp_size.push(perf_stat.resp_len as f64); - resp_t_size.push(perf_stat.resp_t.as_secs_f64()); - resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); - } - - println!("\n-------Trust Promotion--------\n"); - print_stats_test_results( - req_size, - req_t_size, - resp_size, - resp_t_size, - resp_handle_t_size, - ); -} - -#[test] -fn stats_test_trust_level0_migration() { - let mut th = TestHarness::new_buckets(150, 150); - - let mut req_size: Vec = Vec::new(); - let mut resp_size: Vec = Vec::new(); - let mut req_t_size: Vec = Vec::new(); - let mut resp_t_size: Vec = Vec::new(); - let mut resp_handle_t_size: Vec = Vec::new(); - let mut tot_req_size: Vec = Vec::new(); - let mut tot_resp_size: Vec = Vec::new(); - let mut tot_req_t_size: Vec = Vec::new(); - let mut tot_resp_t_size: Vec = Vec::new(); - let mut tot_resp_handle_t_size: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(47); - let (tp_perf_stat, migcred) = th.trust_promotion(&cred); - let (perf_stat, _) = th.level0_migration(&cred, &migcred); - req_size.push(perf_stat.req_len as f64); - req_t_size.push(perf_stat.req_t.as_secs_f64()); - resp_size.push(perf_stat.resp_len as f64); - resp_t_size.push(perf_stat.resp_t.as_secs_f64()); - resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); - tot_req_size.push((perf_stat.req_len + tp_perf_stat.req_len) as f64); - tot_req_t_size.push((perf_stat.req_t + tp_perf_stat.req_t).as_secs_f64()); - tot_resp_size.push((perf_stat.resp_len + tp_perf_stat.resp_len) as f64); - tot_resp_t_size.push((perf_stat.resp_t + tp_perf_stat.resp_t).as_secs_f64()); - tot_resp_handle_t_size - .push((perf_stat.resp_handle_t + tp_perf_stat.resp_handle_t).as_secs_f64()); - } - - println!("\n-------------Trust Level0 Migration----------------\n"); - print_stats_test_results( - req_size, - req_t_size, - resp_size, - resp_t_size, - resp_handle_t_size, - ); - - println!("\n-------Total Trust Promotion to Level 1-------\n"); - print_stats_test_results( - tot_req_size, - tot_req_t_size, - tot_resp_size, - tot_resp_t_size, - tot_resp_handle_t_size, - ); -} - -#[test] -fn stats_test_trust_level_up() { - let mut th = TestHarness::new_buckets(150, 150); - - let mut req_size: Vec = Vec::new(); - let mut resp_size: Vec = Vec::new(); - let mut req_t_size: Vec = Vec::new(); - let mut resp_t_size: Vec = Vec::new(); - let mut resp_handle_t_size: Vec = Vec::new(); + let mut promo_req_size: Vec = Vec::new(); + let mut promo_resp_size: Vec = Vec::new(); + let mut promo_req_time: Vec = Vec::new(); + let mut promo_resp_time: Vec = Vec::new(); + let mut promo_resp_handle_time: Vec = Vec::new(); + let mut mig_req_size: Vec = Vec::new(); + let mut mig_resp_size: Vec = Vec::new(); + let mut mig_req_time: Vec = Vec::new(); + let mut mig_resp_time: Vec = Vec::new(); + let mut mig_resp_handle_time: Vec = Vec::new(); let mut sec_req_size: Vec = Vec::new(); let mut sec_resp_size: Vec = Vec::new(); - let mut sec_req_t_size: Vec = Vec::new(); - let mut sec_resp_t_size: Vec = Vec::new(); - let mut sec_resp_handle_t_size: Vec = Vec::new(); + let mut sec_req_time: Vec = Vec::new(); + let mut sec_resp_time: Vec = Vec::new(); + let mut sec_resp_handle_time: Vec = Vec::new(); let mut three_req_size: Vec = Vec::new(); let mut three_resp_size: Vec = Vec::new(); - let mut three_req_t_size: Vec = Vec::new(); - let mut three_resp_t_size: Vec = Vec::new(); - let mut three_resp_handle_t_size: Vec = Vec::new(); + let mut three_req_time: Vec = Vec::new(); + let mut three_resp_time: Vec = Vec::new(); + let mut three_resp_handle_time: Vec = Vec::new(); let mut four_req_size: Vec = Vec::new(); let mut four_resp_size: Vec = Vec::new(); - let mut four_req_t_size: Vec = Vec::new(); - let mut four_resp_t_size: Vec = Vec::new(); - let mut four_resp_handle_t_size: Vec = Vec::new(); + let mut four_req_time: Vec = Vec::new(); + let mut four_resp_time: Vec = Vec::new(); + let mut four_resp_handle_time: Vec = Vec::new(); + let mut open_req_size: Vec = Vec::new(); + let mut open_resp_size: Vec = Vec::new(); + let mut open_req_time: Vec = Vec::new(); + let mut open_resp_time: Vec = Vec::new(); + let mut open_resp_handle_time: Vec = Vec::new(); for _ in 0..10000 { - let cred = th.open_invite().1 .0; + let (open_perf_stat, cred) = th.open_invite(); th.advance_days(30); - let (tp_perf_stat, migcred) = th.trust_promotion(&cred); - let (perf_stat, cred1) = th.level0_migration(&cred, &migcred); + let (tp_perf_stat, migcred) = th.trust_promotion(&cred.0); + let (mig_perf_stat, cred1) = th.level0_migration(&cred.0, &migcred); th.advance_days(14); let (sec_perf_stat, cred2) = th.level_up(&cred1); th.advance_days(28); let (three_perf_stat, cred3) = th.level_up(&cred2); th.advance_days(56); let (four_perf_stat, _) = th.level_up(&cred3); - req_size.push((perf_stat.req_len + tp_perf_stat.req_len) as f64); - req_t_size.push((perf_stat.req_t + tp_perf_stat.req_t).as_secs_f64()); - resp_size.push((perf_stat.resp_len + tp_perf_stat.resp_len) as f64); - resp_t_size.push((perf_stat.resp_t + tp_perf_stat.resp_t).as_secs_f64()); - resp_handle_t_size - .push((perf_stat.resp_handle_t + tp_perf_stat.resp_handle_t).as_secs_f64()); + open_req_size.push(open_perf_stat.req_len as f64); + open_req_time.push(open_perf_stat.req_t.as_secs_f64()); + open_resp_size.push(open_perf_stat.resp_len as f64); + open_resp_time.push(open_perf_stat.resp_t.as_secs_f64()); + open_resp_handle_time.push(open_perf_stat.resp_handle_t.as_secs_f64()); + promo_req_size.push(tp_perf_stat.req_len as f64); + promo_req_time.push(tp_perf_stat.req_t.as_secs_f64()); + promo_resp_size.push(tp_perf_stat.resp_len as f64); + promo_resp_time.push(tp_perf_stat.resp_t.as_secs_f64()); + promo_resp_handle_time.push(tp_perf_stat.resp_handle_t.as_secs_f64()); + mig_req_size.push(mig_perf_stat.req_len as f64); + mig_req_time.push(mig_perf_stat.req_t.as_secs_f64()); + mig_resp_size.push(mig_perf_stat.resp_len as f64); + mig_resp_time.push(mig_perf_stat.resp_t.as_secs_f64()); + mig_resp_handle_time.push(mig_perf_stat.resp_handle_t.as_secs_f64()); sec_req_size.push(sec_perf_stat.req_len as f64); - sec_req_t_size.push(sec_perf_stat.req_t.as_secs_f64()); + sec_req_time.push(sec_perf_stat.req_t.as_secs_f64()); sec_resp_size.push(sec_perf_stat.resp_len as f64); - sec_resp_t_size.push(sec_perf_stat.resp_t.as_secs_f64()); - sec_resp_handle_t_size.push(sec_perf_stat.resp_handle_t.as_secs_f64()); + sec_resp_time.push(sec_perf_stat.resp_t.as_secs_f64()); + sec_resp_handle_time.push(sec_perf_stat.resp_handle_t.as_secs_f64()); three_req_size.push(three_perf_stat.req_len as f64); - three_req_t_size.push(three_perf_stat.req_t.as_secs_f64()); + three_req_time.push(three_perf_stat.req_t.as_secs_f64()); three_resp_size.push(three_perf_stat.resp_len as f64); - three_resp_t_size.push(three_perf_stat.resp_t.as_secs_f64()); - three_resp_handle_t_size.push(three_perf_stat.resp_handle_t.as_secs_f64()); + three_resp_time.push(three_perf_stat.resp_t.as_secs_f64()); + three_resp_handle_time.push(three_perf_stat.resp_handle_t.as_secs_f64()); four_req_size.push(four_perf_stat.req_len as f64); - four_req_t_size.push(four_perf_stat.req_t.as_secs_f64()); + four_req_time.push(four_perf_stat.req_t.as_secs_f64()); four_resp_size.push(four_perf_stat.resp_len as f64); - four_resp_t_size.push(four_perf_stat.resp_t.as_secs_f64()); - four_resp_handle_t_size.push(four_perf_stat.resp_handle_t.as_secs_f64()); + four_resp_time.push(four_perf_stat.resp_t.as_secs_f64()); + four_resp_handle_time.push(four_perf_stat.resp_handle_t.as_secs_f64()); + println!("OPEN_INVITE"); + print_time_test_results(open_perf_stat); + println!("TRUST_PROMOTION"); + print_time_test_results(tp_perf_stat); + println!("LEVEL_1_MIGRATION"); + print_time_test_results(mig_perf_stat); + println!("LEVEL_2_UP"); + print_time_test_results(sec_perf_stat); + println!("LEVEL_3_UP"); + print_time_test_results(three_perf_stat); + println!("LEVEL_4_UP"); + print_time_test_results(four_perf_stat); } - println!("\n---Trust Promotion + Migration to Level 1: 30 days----\n"); + println!("\n---------------Open Invitationn-------------------\n"); print_stats_test_results( - req_size, - req_t_size, - resp_size, - resp_t_size, - resp_handle_t_size, + open_req_size, + open_req_time, + open_resp_size, + open_resp_time, + open_resp_handle_time, + ); + + println!("\n-------Trust Promotion to Level 1: 30 days----\n"); + print_stats_test_results( + promo_req_size, + promo_req_time, + promo_resp_size, + promo_resp_time, + promo_resp_handle_time, + ); + + println!("\n-------Trust Level 0 Migration: 30 days------------\n"); + print_stats_test_results( + mig_req_size, + mig_req_time, + mig_resp_size, + mig_resp_time, + mig_resp_handle_time, ); println!("\n-------Trust Promotion to Level 2: 44 days-------\n"); print_stats_test_results( sec_req_size, - sec_req_t_size, + sec_req_time, sec_resp_size, - sec_resp_t_size, - sec_resp_handle_t_size, + sec_resp_time, + sec_resp_handle_time, ); println!("\n-------Trust Promotion to Level 3: 72 days------\n"); print_stats_test_results( three_req_size, - three_req_t_size, + three_req_time, three_resp_size, - three_resp_t_size, - three_resp_handle_t_size, + three_resp_time, + three_resp_handle_time, ); println!("\n-------Trust Promotion to Level 4: 128 days------\n"); print_stats_test_results( four_req_size, - four_req_t_size, + four_req_time, four_resp_size, - four_resp_t_size, - four_resp_handle_t_size, + four_resp_time, + four_resp_handle_time, ); } @@ -922,14 +862,14 @@ fn stats_test_invitations() { let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); - let mut req_t_size: Vec = Vec::new(); - let mut resp_t_size: Vec = Vec::new(); - let mut resp_handle_t_size: Vec = Vec::new(); + let mut req_time: Vec = Vec::new(); + let mut resp_time: Vec = Vec::new(); + let mut resp_handle_time: Vec = Vec::new(); let mut red_req_size: Vec = Vec::new(); let mut red_resp_size: Vec = Vec::new(); - let mut red_req_t_size: Vec = Vec::new(); - let mut red_resp_t_size: Vec = Vec::new(); - let mut red_resp_handle_t_size: Vec = Vec::new(); + let mut red_req_time: Vec = Vec::new(); + let mut red_resp_time: Vec = Vec::new(); + let mut red_resp_handle_time: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; th.advance_days(30); @@ -941,33 +881,31 @@ fn stats_test_invitations() { let (perf_stat, (_, invite)) = th.issue_invite(&cred2); let (bob_perf_stat, _) = th.redeem_invite(&invite); req_size.push(perf_stat.req_len as f64); - req_t_size.push(perf_stat.req_t.as_secs_f64()); + req_time.push(perf_stat.req_t.as_secs_f64()); resp_size.push(perf_stat.resp_len as f64); - resp_t_size.push(perf_stat.resp_t.as_secs_f64()); - resp_handle_t_size.push(perf_stat.resp_handle_t.as_secs_f64()); + resp_time.push(perf_stat.resp_t.as_secs_f64()); + resp_handle_time.push(perf_stat.resp_handle_t.as_secs_f64()); red_req_size.push(bob_perf_stat.req_len as f64); - red_req_t_size.push(bob_perf_stat.req_t.as_secs_f64()); + red_req_time.push(bob_perf_stat.req_t.as_secs_f64()); red_resp_size.push(bob_perf_stat.resp_len as f64); - red_resp_t_size.push(bob_perf_stat.resp_t.as_secs_f64()); - red_resp_handle_t_size.push(bob_perf_stat.resp_handle_t.as_secs_f64()); + red_resp_time.push(bob_perf_stat.resp_t.as_secs_f64()); + red_resp_handle_time.push(bob_perf_stat.resp_handle_t.as_secs_f64()); + println!("ISSUE_INVITE"); + print_time_test_results(perf_stat); + println!("REDEEM_INVITE"); + print_time_test_results(bob_perf_stat); } println!("\n---------------Issue Invitation----------------\n"); - print_stats_test_results( - req_size, - req_t_size, - resp_size, - resp_t_size, - resp_handle_t_size, - ); + print_stats_test_results(req_size, req_time, resp_size, resp_time, resp_handle_time); println!("\n---------------Redeem Invitation----------------\n"); print_stats_test_results( red_req_size, - red_req_t_size, + red_req_time, red_resp_size, - red_resp_t_size, - red_resp_handle_t_size, + red_resp_time, + red_resp_handle_time, ); } @@ -1443,14 +1381,14 @@ fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); - let mut req_t_size: Vec = Vec::new(); - let mut resp_t_size: Vec = Vec::new(); - let mut resp_handle_t_size: Vec = Vec::new(); + let mut req_time: Vec = Vec::new(); + let mut resp_time: Vec = Vec::new(); + let mut resp_handle_time: Vec = Vec::new(); let mut red_req_size: Vec = Vec::new(); let mut red_resp_size: Vec = Vec::new(); - let mut red_req_t_size: Vec = Vec::new(); - let mut red_resp_t_size: Vec = Vec::new(); - let mut red_resp_handle_t_size: Vec = Vec::new(); + let mut red_req_time: Vec = Vec::new(); + let mut red_resp_time: Vec = Vec::new(); + let mut red_resp_handle_time: Vec = Vec::new(); for cred in credentials { let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); let encbuckets = th.ba.enc_bridge_table(); @@ -1468,15 +1406,19 @@ fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec, - req_t_size: Vec, + req_time: Vec, resp_size: Vec, - resp_t_size: Vec, - resp_handle_t_size: Vec, + resp_time: Vec, + resp_handle_time: Vec, ) { let mean_req_size = mean(&req_size); let req_std_dev = standard_deviation(&req_size, Some(mean_req_size)); - let mean_req_t_size = mean(&req_t_size); - let req_t_std_dev = standard_deviation(&req_t_size, Some(mean_req_t_size)); + let mean_req_time = mean(&req_time); + let req_time_std_dev = standard_deviation(&req_time, Some(mean_req_time)); let mean_resp_size = mean(&resp_size); let resp_std_dev = standard_deviation(&resp_size, Some(mean_resp_size)); - let mean_resp_t_size = mean(&resp_t_size); - let resp_t_std_dev = standard_deviation(&resp_t_size, Some(mean_resp_t_size)); - let mean_resp_handle_t_size = mean(&resp_handle_t_size); - let resp_handle_t_std_dev = - standard_deviation(&resp_handle_t_size, Some(mean_resp_handle_t_size)); + let mean_resp_time = mean(&resp_time); + let resp_time_std_dev = standard_deviation(&resp_time, Some(mean_resp_time)); + let mean_resp_handle_time = mean(&resp_handle_time); + let resp_handle_time_std_dev = + standard_deviation(&resp_handle_time, Some(mean_resp_handle_time)); println!("Average request size = {} bytes", mean_req_size); println!("Request size standard deviation = {} bytes", req_std_dev); println!( "Average request time = {:?}", - Duration::from_secs_f64(mean_req_t_size) + Duration::from_secs_f64(mean_req_time) ); println!( "Request time standard deviation = {:?}", - Duration::from_secs_f64(req_t_std_dev) + Duration::from_secs_f64(req_time_std_dev) ); println!("Average response size = {} bytes", mean_resp_size); println!("Response standard deviation = {} bytes", resp_std_dev); println!( "Average response time = {:?}", - Duration::from_secs_f64(mean_resp_t_size) + Duration::from_secs_f64(mean_resp_time) ); println!( "Response time standard deviation = {:?}", - Duration::from_secs_f64(resp_t_std_dev) + Duration::from_secs_f64(resp_time_std_dev) ); println!( "Average response handling time = {:?}", - Duration::from_secs_f64(mean_resp_handle_t_size) + Duration::from_secs_f64(mean_resp_handle_time) ); println!( "Response handling time standard deviation = {:?}", - Duration::from_secs_f64(resp_handle_t_std_dev) + Duration::from_secs_f64(resp_handle_time_std_dev) ); } From 3bb50aa9ab5a55d54f9ad22e6d7c3aff69ae1d57 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 22 Nov 2021 22:56:48 -0500 Subject: [PATCH 071/115] Added tests for different sized bridges --- crates/lox-library/src/tests.rs | 405 ++++++++++++++++++++++++-------- 1 file changed, 308 insertions(+), 97 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 0b21dd3..660452d 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -28,7 +28,7 @@ impl TestHarness { TestHarness::new_buckets(5, 5) } - fn new_buckets(num_buckets: u8, hot_spare: u8) -> Self { + fn new_buckets(num_buckets: u16, hot_spare: u16) -> Self { // Create a BridegDb let mut bdb = BridgeDb::new(); // Create a BridgeAuth @@ -712,9 +712,9 @@ fn test_blockage_migration() { assert!(th.ba.verify_lox(&cred4)); } -#[test] -fn stats_test_trust_levels() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_trust_levels(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut promo_req_size: Vec = Vec::new(); let mut promo_resp_size: Vec = Vec::new(); @@ -787,21 +787,21 @@ fn stats_test_trust_levels() { four_resp_size.push(four_perf_stat.resp_len as f64); four_resp_time.push(four_perf_stat.resp_t.as_secs_f64()); four_resp_handle_time.push(four_perf_stat.resp_handle_t.as_secs_f64()); - println!("OPEN_INVITE"); - print_time_test_results(open_perf_stat); - println!("TRUST_PROMOTION"); - print_time_test_results(tp_perf_stat); - println!("LEVEL_1_MIGRATION"); - print_time_test_results(mig_perf_stat); - println!("LEVEL_2_UP"); - print_time_test_results(sec_perf_stat); - println!("LEVEL_3_UP"); - print_time_test_results(three_perf_stat); - println!("LEVEL_4_UP"); - print_time_test_results(four_perf_stat); + // println!("OPEN_INVITE"); + // print_time_test_results(open_perf_stat); + // println!("TRUST_PROMOTION"); + // print_time_test_results(tp_perf_stat); + // println!("LEVEL_1_MIGRATION"); + // print_time_test_results(mig_perf_stat); + // println!("LEVEL_2_UP"); + // print_time_test_results(sec_perf_stat); + // println!("LEVEL_3_UP"); + // print_time_test_results(three_perf_stat); + // println!("LEVEL_4_UP"); + // print_time_test_results(four_perf_stat); } - println!("\n---------------Open Invitationn-------------------\n"); + println!("\n----OPEN-INVITATION----\n"); print_stats_test_results( open_req_size, open_req_time, @@ -810,7 +810,7 @@ fn stats_test_trust_levels() { open_resp_handle_time, ); - println!("\n-------Trust Promotion to Level 1: 30 days----\n"); + println!("\n----TRUST-PROMOTION-1: 30 days----\n"); print_stats_test_results( promo_req_size, promo_req_time, @@ -819,7 +819,7 @@ fn stats_test_trust_levels() { promo_resp_handle_time, ); - println!("\n-------Trust Level 0 Migration: 30 days------------\n"); + println!("\n----TRUST-MIGRATION-0: 30 days------------\n"); print_stats_test_results( mig_req_size, mig_req_time, @@ -828,7 +828,7 @@ fn stats_test_trust_levels() { mig_resp_handle_time, ); - println!("\n-------Trust Promotion to Level 2: 44 days-------\n"); + println!("\n----LEVEL-UP-2: 44 days----\n"); print_stats_test_results( sec_req_size, sec_req_time, @@ -837,7 +837,7 @@ fn stats_test_trust_levels() { sec_resp_handle_time, ); - println!("\n-------Trust Promotion to Level 3: 72 days------\n"); + println!("\n----LEVEL-UP-3: 72 days------\n"); print_stats_test_results( three_req_size, three_req_time, @@ -846,7 +846,7 @@ fn stats_test_trust_levels() { three_resp_handle_time, ); - println!("\n-------Trust Promotion to Level 4: 128 days------\n"); + println!("\n----LEVEL-UP-4: 128 days------\n"); print_stats_test_results( four_req_size, four_req_time, @@ -856,9 +856,9 @@ fn stats_test_trust_levels() { ); } -#[test] -fn stats_test_invitations() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_invitations(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut req_size: Vec = Vec::new(); let mut resp_size: Vec = Vec::new(); @@ -890,16 +890,12 @@ fn stats_test_invitations() { red_resp_size.push(bob_perf_stat.resp_len as f64); red_resp_time.push(bob_perf_stat.resp_t.as_secs_f64()); red_resp_handle_time.push(bob_perf_stat.resp_handle_t.as_secs_f64()); - println!("ISSUE_INVITE"); - print_time_test_results(perf_stat); - println!("REDEEM_INVITE"); - print_time_test_results(bob_perf_stat); } - println!("\n---------------Issue Invitation----------------\n"); + println!("\n----ISSUE-INVITATION----\n"); print_stats_test_results(req_size, req_time, resp_size, resp_time, resp_handle_time); - println!("\n---------------Redeem Invitation----------------\n"); + println!("\n----REDEEM-INVITATION----\n"); print_stats_test_results( red_req_size, red_req_time, @@ -909,9 +905,9 @@ fn stats_test_invitations() { ); } -#[test] -fn stats_test_blockage_migration_5() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_5(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..1000 { let cred = th.open_invite().1 .0; @@ -931,9 +927,9 @@ fn stats_test_blockage_migration_5() { block_bridges(&mut th, 5, credentials); } -#[test] -fn stats_test_blockage_migration_10() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_10(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..1000 { let cred = th.open_invite().1 .0; @@ -953,9 +949,9 @@ fn stats_test_blockage_migration_10() { block_bridges(&mut th, 10, credentials); } -#[test] -fn stats_test_blockage_migration_15() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_15(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -975,9 +971,9 @@ fn stats_test_blockage_migration_15() { block_bridges(&mut th, 15, credentials); } -#[test] -fn stats_test_blockage_migration_20() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_20(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -997,9 +993,9 @@ fn stats_test_blockage_migration_20() { block_bridges(&mut th, 20, credentials); } -#[test] -fn stats_test_blockage_migration_25() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_25(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1019,9 +1015,9 @@ fn stats_test_blockage_migration_25() { block_bridges(&mut th, 25, credentials); } -#[test] -fn stats_test_blockage_migration_30() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_30(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1041,9 +1037,9 @@ fn stats_test_blockage_migration_30() { block_bridges(&mut th, 30, credentials); } -#[test] -fn stats_test_blockage_migration_35() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_35(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1063,9 +1059,9 @@ fn stats_test_blockage_migration_35() { block_bridges(&mut th, 35, credentials); } -#[test] -fn stats_test_blockage_migration_40() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_40(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1085,9 +1081,9 @@ fn stats_test_blockage_migration_40() { block_bridges(&mut th, 40, credentials); } -#[test] -fn stats_test_blockage_migration_45() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_45(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1107,9 +1103,9 @@ fn stats_test_blockage_migration_45() { block_bridges(&mut th, 45, credentials); } -#[test] -fn stats_test_blockage_migration_50() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_50(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1129,9 +1125,9 @@ fn stats_test_blockage_migration_50() { block_bridges(&mut th, 50, credentials); } -#[test] -fn stats_test_blockage_migration_55() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_55(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1151,9 +1147,9 @@ fn stats_test_blockage_migration_55() { block_bridges(&mut th, 55, credentials); } -#[test] -fn stats_test_blockage_migration_60() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_60(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1173,9 +1169,9 @@ fn stats_test_blockage_migration_60() { block_bridges(&mut th, 60, credentials); } -#[test] -fn stats_test_blockage_migration_65() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_65(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1195,9 +1191,9 @@ fn stats_test_blockage_migration_65() { block_bridges(&mut th, 65, credentials); } -#[test] -fn stats_test_blockage_migration_70() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_70(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1217,9 +1213,9 @@ fn stats_test_blockage_migration_70() { block_bridges(&mut th, 70, credentials); } -#[test] -fn stats_test_blockage_migration_75() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_75(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1239,9 +1235,9 @@ fn stats_test_blockage_migration_75() { block_bridges(&mut th, 75, credentials); } -#[test] -fn stats_test_blockage_migration_80() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_80(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1261,9 +1257,9 @@ fn stats_test_blockage_migration_80() { block_bridges(&mut th, 80, credentials); } -#[test] -fn stats_test_blockage_migration_85() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_85(buckets: u16) { + let mut th = TestHarness::new_buckets(buckets, buckets); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1283,9 +1279,9 @@ fn stats_test_blockage_migration_85() { block_bridges(&mut th, 85, credentials); } -#[test] -fn stats_test_blockage_migration_90() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_90(bucket: u16) { + let mut th = TestHarness::new_buckets(bucket, bucket); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1305,9 +1301,9 @@ fn stats_test_blockage_migration_90() { block_bridges(&mut th, 90, credentials); } -#[test] -fn stats_test_blockage_migration_95() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_95(bucket: u16) { + let mut th = TestHarness::new_buckets(bucket, bucket); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1327,9 +1323,9 @@ fn stats_test_blockage_migration_95() { block_bridges(&mut th, 95, credentials); } -#[test] -fn stats_test_blockage_migration_100() { - let mut th = TestHarness::new_buckets(150, 150); +//#[test] +fn stats_test_blockage_migration_100(bucket: u16) { + let mut th = TestHarness::new_buckets(bucket, bucket); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { let cred = th.open_invite().1 .0; @@ -1349,6 +1345,220 @@ fn stats_test_blockage_migration_100() { block_bridges(&mut th, 100, credentials); } +//#[test] Check if times/sizes change after blocking +fn stats_test_blockage_migration_incremental_and_levels(buckets: u16) { + println!("\n----WEIRD-TEST----\n"); + let mut th = TestHarness::new_buckets(buckets, buckets); + for _ in 0..15{ + let mut req_size: Vec = Vec::new(); + let mut resp_size: Vec = Vec::new(); + let mut req_time: Vec = Vec::new(); + let mut resp_time: Vec = Vec::new(); + let mut resp_handle_time: Vec = Vec::new(); + let mut red_req_size: Vec = Vec::new(); + let mut red_resp_size: Vec = Vec::new(); + let mut red_req_time: Vec = Vec::new(); + let mut red_resp_time: Vec = Vec::new(); + let mut red_resp_handle_time: Vec = Vec::new(); + let mut promo_req_size: Vec = Vec::new(); + let mut promo_resp_size: Vec = Vec::new(); + let mut promo_req_time: Vec = Vec::new(); + let mut promo_resp_time: Vec = Vec::new(); + let mut promo_resp_handle_time: Vec = Vec::new(); + let mut mig_req_size: Vec = Vec::new(); + let mut mig_resp_size: Vec = Vec::new(); + let mut mig_req_time: Vec = Vec::new(); + let mut mig_resp_time: Vec = Vec::new(); + let mut mig_resp_handle_time: Vec = Vec::new(); + let mut sec_req_size: Vec = Vec::new(); + let mut sec_resp_size: Vec = Vec::new(); + let mut sec_req_time: Vec = Vec::new(); + let mut sec_resp_time: Vec = Vec::new(); + let mut sec_resp_handle_time: Vec = Vec::new(); + let mut three_req_size: Vec = Vec::new(); + let mut three_resp_size: Vec = Vec::new(); + let mut three_req_time: Vec = Vec::new(); + let mut three_resp_time: Vec = Vec::new(); + let mut three_resp_handle_time: Vec = Vec::new(); + let mut four_req_size: Vec = Vec::new(); + let mut four_resp_size: Vec = Vec::new(); + let mut four_req_time: Vec = Vec::new(); + let mut four_resp_time: Vec = Vec::new(); + let mut four_resp_handle_time: Vec = Vec::new(); + let mut open_req_size: Vec = Vec::new(); + let mut open_resp_size: Vec = Vec::new(); + let mut open_req_time: Vec = Vec::new(); + let mut open_resp_time: Vec = Vec::new(); + let mut open_resp_handle_time: Vec = Vec::new(); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let (open_perf_stat, cred) = th.open_invite(); + th.advance_days(30); + let (tp_perf_stat, migcred) = th.trust_promotion(&cred.0); + let (mig_perf_stat, cred1) = th.level0_migration(&cred.0, &migcred); + th.advance_days(14); + let (sec_perf_stat, cred2) = th.level_up(&cred1); + let (perf_stat, (cred2a, invite)) = th.issue_invite(&cred2); + let (bob_perf_stat, _) = th.redeem_invite(&invite); + th.advance_days(28); + let (three_perf_stat, cred3) = th.level_up(&cred2a); + th.advance_days(56); + let (four_perf_stat, cred4) = th.level_up(&cred3); + credentials.push(cred4); + open_req_size.push(open_perf_stat.req_len as f64); + open_req_time.push(open_perf_stat.req_t.as_secs_f64()); + open_resp_size.push(open_perf_stat.resp_len as f64); + open_resp_time.push(open_perf_stat.resp_t.as_secs_f64()); + open_resp_handle_time.push(open_perf_stat.resp_handle_t.as_secs_f64()); + promo_req_size.push(tp_perf_stat.req_len as f64); + promo_req_time.push(tp_perf_stat.req_t.as_secs_f64()); + promo_resp_size.push(tp_perf_stat.resp_len as f64); + promo_resp_time.push(tp_perf_stat.resp_t.as_secs_f64()); + promo_resp_handle_time.push(tp_perf_stat.resp_handle_t.as_secs_f64()); + mig_req_size.push(mig_perf_stat.req_len as f64); + mig_req_time.push(mig_perf_stat.req_t.as_secs_f64()); + mig_resp_size.push(mig_perf_stat.resp_len as f64); + mig_resp_time.push(mig_perf_stat.resp_t.as_secs_f64()); + mig_resp_handle_time.push(mig_perf_stat.resp_handle_t.as_secs_f64()); + sec_req_size.push(sec_perf_stat.req_len as f64); + sec_req_time.push(sec_perf_stat.req_t.as_secs_f64()); + sec_resp_size.push(sec_perf_stat.resp_len as f64); + sec_resp_time.push(sec_perf_stat.resp_t.as_secs_f64()); + sec_resp_handle_time.push(sec_perf_stat.resp_handle_t.as_secs_f64()); + three_req_size.push(three_perf_stat.req_len as f64); + three_req_time.push(three_perf_stat.req_t.as_secs_f64()); + three_resp_size.push(three_perf_stat.resp_len as f64); + three_resp_time.push(three_perf_stat.resp_t.as_secs_f64()); + three_resp_handle_time.push(three_perf_stat.resp_handle_t.as_secs_f64()); + four_req_size.push(four_perf_stat.req_len as f64); + four_req_time.push(four_perf_stat.req_t.as_secs_f64()); + four_resp_size.push(four_perf_stat.resp_len as f64); + four_resp_time.push(four_perf_stat.resp_t.as_secs_f64()); + four_resp_handle_time.push(four_perf_stat.resp_handle_t.as_secs_f64()); + req_size.push(perf_stat.req_len as f64); + req_time.push(perf_stat.req_t.as_secs_f64()); + resp_size.push(perf_stat.resp_len as f64); + resp_time.push(perf_stat.resp_t.as_secs_f64()); + resp_handle_time.push(perf_stat.resp_handle_t.as_secs_f64()); + red_req_size.push(bob_perf_stat.req_len as f64); + red_req_time.push(bob_perf_stat.req_t.as_secs_f64()); + red_resp_size.push(bob_perf_stat.resp_len as f64); + red_resp_time.push(bob_perf_stat.resp_t.as_secs_f64()); + red_resp_handle_time.push(bob_perf_stat.resp_handle_t.as_secs_f64()); + + } + + println!("\n----WEIRD-OPEN-INVITATION----\n"); + print_stats_test_results( + open_req_size, + open_req_time, + open_resp_size, + open_resp_time, + open_resp_handle_time, + ); + + println!("\n----WEIRD-TRUST-PROMOTION-1: 30 days----\n"); + print_stats_test_results( + promo_req_size, + promo_req_time, + promo_resp_size, + promo_resp_time, + promo_resp_handle_time, + ); + + println!("\n----WEIRD-TRUST-MIGRATION-0: 30 days------------\n"); + print_stats_test_results( + mig_req_size, + mig_req_time, + mig_resp_size, + mig_resp_time, + mig_resp_handle_time, + ); + + println!("\n----WEIRD-LEVEL-UP-2: 44 days----\n"); + print_stats_test_results( + sec_req_size, + sec_req_time, + sec_resp_size, + sec_resp_time, + sec_resp_handle_time, + ); + + println!("\n----WEIRD-LEVEL-UP-3: 72 days------\n"); + print_stats_test_results( + three_req_size, + three_req_time, + three_resp_size, + three_resp_time, + three_resp_handle_time, + ); + + println!("\n----WEIRD-LEVEL-UP-4: 128 days------\n"); + print_stats_test_results( + four_req_size, + four_req_time, + four_resp_size, + four_resp_time, + four_resp_handle_time, + ); + println!("\n----ISSUE-INVITATION----\n"); + print_stats_test_results(req_size, req_time, resp_size, resp_time, resp_handle_time); + println!("\n----REDEEM-INVITATION----\n"); + print_stats_test_results( + red_req_size, + red_req_time, + red_resp_size, + red_resp_time, + red_resp_handle_time, + ); + + + block_bridges(&mut th, 10, credentials); + } +} + +#[test] +fn test_all(){ + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + println!("\n***START: {}*3*2 BUCKETS***\n", x); + stats_test_trust_levels(x); + stats_test_invitations(x); + stats_test_blockage_migration_5(x); + stats_test_blockage_migration_10(x); + stats_test_blockage_migration_15(x); + stats_test_blockage_migration_20(x); + stats_test_blockage_migration_25(x); + stats_test_blockage_migration_30(x); + stats_test_blockage_migration_35(x); + stats_test_blockage_migration_40(x); + stats_test_blockage_migration_45(x); + stats_test_blockage_migration_50(x); + stats_test_blockage_migration_55(x); + stats_test_blockage_migration_60(x); + stats_test_blockage_migration_65(x); + stats_test_blockage_migration_70(x); + stats_test_blockage_migration_75(x); + stats_test_blockage_migration_80(x); + stats_test_blockage_migration_85(x); + stats_test_blockage_migration_90(x); + stats_test_blockage_migration_95(x); + stats_test_blockage_migration_100(x); + + } + + let buckets2: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + for x in buckets2 { + println!("\n***START: {}*3*2 BUCKETS FOR WEIRD TEST***\n", x); + stats_test_blockage_migration_incremental_and_levels(x); + + } + + println!("\nAll done!\n"); + +} + /// Blocks a percentage of the bridges for the passed Test Harness /// excluding the hot spare buckets as they will not have been handed out. /// The logic assumes hot spare buckets are appended to the end of the bridge_table @@ -1415,21 +1625,21 @@ fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec Date: Tue, 23 Nov 2021 17:02:34 +0000 Subject: [PATCH 072/115] Changed printout statements and reverted to multithreaded testing --- crates/lox-library/src/tests.rs | 1444 ++++++++++++++----------------- 1 file changed, 658 insertions(+), 786 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 660452d..17450e2 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -712,685 +712,43 @@ fn test_blockage_migration() { assert!(th.ba.verify_lox(&cred4)); } -//#[test] -fn stats_test_trust_levels(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); +#[test] +fn stats_test_trust_levels() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - let mut promo_req_size: Vec = Vec::new(); - let mut promo_resp_size: Vec = Vec::new(); - let mut promo_req_time: Vec = Vec::new(); - let mut promo_resp_time: Vec = Vec::new(); - let mut promo_resp_handle_time: Vec = Vec::new(); - let mut mig_req_size: Vec = Vec::new(); - let mut mig_resp_size: Vec = Vec::new(); - let mut mig_req_time: Vec = Vec::new(); - let mut mig_resp_time: Vec = Vec::new(); - let mut mig_resp_handle_time: Vec = Vec::new(); - let mut sec_req_size: Vec = Vec::new(); - let mut sec_resp_size: Vec = Vec::new(); - let mut sec_req_time: Vec = Vec::new(); - let mut sec_resp_time: Vec = Vec::new(); - let mut sec_resp_handle_time: Vec = Vec::new(); - let mut three_req_size: Vec = Vec::new(); - let mut three_resp_size: Vec = Vec::new(); - let mut three_req_time: Vec = Vec::new(); - let mut three_resp_time: Vec = Vec::new(); - let mut three_resp_handle_time: Vec = Vec::new(); - let mut four_req_size: Vec = Vec::new(); - let mut four_resp_size: Vec = Vec::new(); - let mut four_req_time: Vec = Vec::new(); - let mut four_resp_time: Vec = Vec::new(); - let mut four_resp_handle_time: Vec = Vec::new(); - let mut open_req_size: Vec = Vec::new(); - let mut open_resp_size: Vec = Vec::new(); - let mut open_req_time: Vec = Vec::new(); - let mut open_resp_time: Vec = Vec::new(); - let mut open_resp_handle_time: Vec = Vec::new(); - for _ in 0..10000 { - let (open_perf_stat, cred) = th.open_invite(); - th.advance_days(30); - let (tp_perf_stat, migcred) = th.trust_promotion(&cred.0); - let (mig_perf_stat, cred1) = th.level0_migration(&cred.0, &migcred); - th.advance_days(14); - let (sec_perf_stat, cred2) = th.level_up(&cred1); - th.advance_days(28); - let (three_perf_stat, cred3) = th.level_up(&cred2); - th.advance_days(56); - let (four_perf_stat, _) = th.level_up(&cred3); - open_req_size.push(open_perf_stat.req_len as f64); - open_req_time.push(open_perf_stat.req_t.as_secs_f64()); - open_resp_size.push(open_perf_stat.resp_len as f64); - open_resp_time.push(open_perf_stat.resp_t.as_secs_f64()); - open_resp_handle_time.push(open_perf_stat.resp_handle_t.as_secs_f64()); - promo_req_size.push(tp_perf_stat.req_len as f64); - promo_req_time.push(tp_perf_stat.req_t.as_secs_f64()); - promo_resp_size.push(tp_perf_stat.resp_len as f64); - promo_resp_time.push(tp_perf_stat.resp_t.as_secs_f64()); - promo_resp_handle_time.push(tp_perf_stat.resp_handle_t.as_secs_f64()); - mig_req_size.push(mig_perf_stat.req_len as f64); - mig_req_time.push(mig_perf_stat.req_t.as_secs_f64()); - mig_resp_size.push(mig_perf_stat.resp_len as f64); - mig_resp_time.push(mig_perf_stat.resp_t.as_secs_f64()); - mig_resp_handle_time.push(mig_perf_stat.resp_handle_t.as_secs_f64()); - sec_req_size.push(sec_perf_stat.req_len as f64); - sec_req_time.push(sec_perf_stat.req_t.as_secs_f64()); - sec_resp_size.push(sec_perf_stat.resp_len as f64); - sec_resp_time.push(sec_perf_stat.resp_t.as_secs_f64()); - sec_resp_handle_time.push(sec_perf_stat.resp_handle_t.as_secs_f64()); - three_req_size.push(three_perf_stat.req_len as f64); - three_req_time.push(three_perf_stat.req_t.as_secs_f64()); - three_resp_size.push(three_perf_stat.resp_len as f64); - three_resp_time.push(three_perf_stat.resp_t.as_secs_f64()); - three_resp_handle_time.push(three_perf_stat.resp_handle_t.as_secs_f64()); - four_req_size.push(four_perf_stat.req_len as f64); - four_req_time.push(four_perf_stat.req_t.as_secs_f64()); - four_resp_size.push(four_perf_stat.resp_len as f64); - four_resp_time.push(four_perf_stat.resp_t.as_secs_f64()); - four_resp_handle_time.push(four_perf_stat.resp_handle_t.as_secs_f64()); - // println!("OPEN_INVITE"); - // print_time_test_results(open_perf_stat); - // println!("TRUST_PROMOTION"); - // print_time_test_results(tp_perf_stat); - // println!("LEVEL_1_MIGRATION"); - // print_time_test_results(mig_perf_stat); - // println!("LEVEL_2_UP"); - // print_time_test_results(sec_perf_stat); - // println!("LEVEL_3_UP"); - // print_time_test_results(three_perf_stat); - // println!("LEVEL_4_UP"); - // print_time_test_results(four_perf_stat); - } + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); - println!("\n----OPEN-INVITATION----\n"); - print_stats_test_results( - open_req_size, - open_req_time, - open_resp_size, - open_resp_time, - open_resp_handle_time, - ); - - println!("\n----TRUST-PROMOTION-1: 30 days----\n"); - print_stats_test_results( - promo_req_size, - promo_req_time, - promo_resp_size, - promo_resp_time, - promo_resp_handle_time, - ); - - println!("\n----TRUST-MIGRATION-0: 30 days------------\n"); - print_stats_test_results( - mig_req_size, - mig_req_time, - mig_resp_size, - mig_resp_time, - mig_resp_handle_time, - ); - - println!("\n----LEVEL-UP-2: 44 days----\n"); - print_stats_test_results( - sec_req_size, - sec_req_time, - sec_resp_size, - sec_resp_time, - sec_resp_handle_time, - ); - - println!("\n----LEVEL-UP-3: 72 days------\n"); - print_stats_test_results( - three_req_size, - three_req_time, - three_resp_size, - three_resp_time, - three_resp_handle_time, - ); - - println!("\n----LEVEL-UP-4: 128 days------\n"); - print_stats_test_results( - four_req_size, - four_req_time, - four_resp_size, - four_resp_time, - four_resp_handle_time, - ); -} - -//#[test] -fn stats_test_invitations(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - - let mut req_size: Vec = Vec::new(); - let mut resp_size: Vec = Vec::new(); - let mut req_time: Vec = Vec::new(); - let mut resp_time: Vec = Vec::new(); - let mut resp_handle_time: Vec = Vec::new(); - let mut red_req_size: Vec = Vec::new(); - let mut red_resp_size: Vec = Vec::new(); - let mut red_req_time: Vec = Vec::new(); - let mut red_resp_time: Vec = Vec::new(); - let mut red_resp_handle_time: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - th.advance_days(28); - let (perf_stat, (_, invite)) = th.issue_invite(&cred2); - let (bob_perf_stat, _) = th.redeem_invite(&invite); - req_size.push(perf_stat.req_len as f64); - req_time.push(perf_stat.req_t.as_secs_f64()); - resp_size.push(perf_stat.resp_len as f64); - resp_time.push(perf_stat.resp_t.as_secs_f64()); - resp_handle_time.push(perf_stat.resp_handle_t.as_secs_f64()); - red_req_size.push(bob_perf_stat.req_len as f64); - red_req_time.push(bob_perf_stat.req_t.as_secs_f64()); - red_resp_size.push(bob_perf_stat.resp_len as f64); - red_resp_time.push(bob_perf_stat.resp_t.as_secs_f64()); - red_resp_handle_time.push(bob_perf_stat.resp_handle_t.as_secs_f64()); - } - - println!("\n----ISSUE-INVITATION----\n"); - print_stats_test_results(req_size, req_time, resp_size, resp_time, resp_handle_time); - - println!("\n----REDEEM-INVITATION----\n"); - print_stats_test_results( - red_req_size, - red_req_time, - red_resp_size, - red_resp_time, - red_resp_handle_time, - ); -} - -//#[test] -fn stats_test_blockage_migration_5(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..1000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 5, credentials); -} - -//#[test] -fn stats_test_blockage_migration_10(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..1000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 10, credentials); -} - -//#[test] -fn stats_test_blockage_migration_15(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 15, credentials); -} - -//#[test] -fn stats_test_blockage_migration_20(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 20, credentials); -} - -//#[test] -fn stats_test_blockage_migration_25(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 25, credentials); -} - -//#[test] -fn stats_test_blockage_migration_30(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 30, credentials); -} - -//#[test] -fn stats_test_blockage_migration_35(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 35, credentials); -} - -//#[test] -fn stats_test_blockage_migration_40(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 40, credentials); -} - -//#[test] -fn stats_test_blockage_migration_45(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 45, credentials); -} - -//#[test] -fn stats_test_blockage_migration_50(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 50, credentials); -} - -//#[test] -fn stats_test_blockage_migration_55(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 55, credentials); -} - -//#[test] -fn stats_test_blockage_migration_60(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 60, credentials); -} - -//#[test] -fn stats_test_blockage_migration_65(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 65, credentials); -} - -//#[test] -fn stats_test_blockage_migration_70(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 70, credentials); -} - -//#[test] -fn stats_test_blockage_migration_75(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 75, credentials); -} - -//#[test] -fn stats_test_blockage_migration_80(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 80, credentials); -} - -//#[test] -fn stats_test_blockage_migration_85(buckets: u16) { - let mut th = TestHarness::new_buckets(buckets, buckets); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 85, credentials); -} - -//#[test] -fn stats_test_blockage_migration_90(bucket: u16) { - let mut th = TestHarness::new_buckets(bucket, bucket); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 90, credentials); -} - -//#[test] -fn stats_test_blockage_migration_95(bucket: u16) { - let mut th = TestHarness::new_buckets(bucket, bucket); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 95, credentials); -} - -//#[test] -fn stats_test_blockage_migration_100(bucket: u16) { - let mut th = TestHarness::new_buckets(bucket, bucket); - let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - block_bridges(&mut th, 100, credentials); -} - -//#[test] Check if times/sizes change after blocking -fn stats_test_blockage_migration_incremental_and_levels(buckets: u16) { - println!("\n----WEIRD-TEST----\n"); - let mut th = TestHarness::new_buckets(buckets, buckets); - for _ in 0..15{ - let mut req_size: Vec = Vec::new(); - let mut resp_size: Vec = Vec::new(); - let mut req_time: Vec = Vec::new(); - let mut resp_time: Vec = Vec::new(); - let mut resp_handle_time: Vec = Vec::new(); - let mut red_req_size: Vec = Vec::new(); - let mut red_resp_size: Vec = Vec::new(); - let mut red_req_time: Vec = Vec::new(); - let mut red_resp_time: Vec = Vec::new(); - let mut red_resp_handle_time: Vec = Vec::new(); - let mut promo_req_size: Vec = Vec::new(); - let mut promo_resp_size: Vec = Vec::new(); - let mut promo_req_time: Vec = Vec::new(); - let mut promo_resp_time: Vec = Vec::new(); - let mut promo_resp_handle_time: Vec = Vec::new(); - let mut mig_req_size: Vec = Vec::new(); - let mut mig_resp_size: Vec = Vec::new(); - let mut mig_req_time: Vec = Vec::new(); - let mut mig_resp_time: Vec = Vec::new(); - let mut mig_resp_handle_time: Vec = Vec::new(); - let mut sec_req_size: Vec = Vec::new(); - let mut sec_resp_size: Vec = Vec::new(); - let mut sec_req_time: Vec = Vec::new(); - let mut sec_resp_time: Vec = Vec::new(); - let mut sec_resp_handle_time: Vec = Vec::new(); - let mut three_req_size: Vec = Vec::new(); - let mut three_resp_size: Vec = Vec::new(); - let mut three_req_time: Vec = Vec::new(); - let mut three_resp_time: Vec = Vec::new(); - let mut three_resp_handle_time: Vec = Vec::new(); - let mut four_req_size: Vec = Vec::new(); - let mut four_resp_size: Vec = Vec::new(); - let mut four_req_time: Vec = Vec::new(); - let mut four_resp_time: Vec = Vec::new(); - let mut four_resp_handle_time: Vec = Vec::new(); - let mut open_req_size: Vec = Vec::new(); - let mut open_resp_size: Vec = Vec::new(); - let mut open_req_time: Vec = Vec::new(); - let mut open_resp_time: Vec = Vec::new(); - let mut open_resp_handle_time: Vec = Vec::new(); - let mut credentials: Vec = Vec::new(); + let mut promo_req_size: Vec = Vec::new(); + let mut promo_resp_size: Vec = Vec::new(); + let mut promo_req_time: Vec = Vec::new(); + let mut promo_resp_time: Vec = Vec::new(); + let mut promo_resp_handle_time: Vec = Vec::new(); + let mut mig_req_size: Vec = Vec::new(); + let mut mig_resp_size: Vec = Vec::new(); + let mut mig_req_time: Vec = Vec::new(); + let mut mig_resp_time: Vec = Vec::new(); + let mut mig_resp_handle_time: Vec = Vec::new(); + let mut sec_req_size: Vec = Vec::new(); + let mut sec_resp_size: Vec = Vec::new(); + let mut sec_req_time: Vec = Vec::new(); + let mut sec_resp_time: Vec = Vec::new(); + let mut sec_resp_handle_time: Vec = Vec::new(); + let mut three_req_size: Vec = Vec::new(); + let mut three_resp_size: Vec = Vec::new(); + let mut three_req_time: Vec = Vec::new(); + let mut three_resp_time: Vec = Vec::new(); + let mut three_resp_handle_time: Vec = Vec::new(); + let mut four_req_size: Vec = Vec::new(); + let mut four_resp_size: Vec = Vec::new(); + let mut four_req_time: Vec = Vec::new(); + let mut four_resp_time: Vec = Vec::new(); + let mut four_resp_handle_time: Vec = Vec::new(); + let mut open_req_size: Vec = Vec::new(); + let mut open_resp_size: Vec = Vec::new(); + let mut open_req_time: Vec = Vec::new(); + let mut open_resp_time: Vec = Vec::new(); + let mut open_resp_handle_time: Vec = Vec::new(); for _ in 0..10000 { let (open_perf_stat, cred) = th.open_invite(); th.advance_days(30); @@ -1398,13 +756,10 @@ fn stats_test_blockage_migration_incremental_and_levels(buckets: u16) { let (mig_perf_stat, cred1) = th.level0_migration(&cred.0, &migcred); th.advance_days(14); let (sec_perf_stat, cred2) = th.level_up(&cred1); - let (perf_stat, (cred2a, invite)) = th.issue_invite(&cred2); - let (bob_perf_stat, _) = th.redeem_invite(&invite); th.advance_days(28); - let (three_perf_stat, cred3) = th.level_up(&cred2a); + let (three_perf_stat, cred3) = th.level_up(&cred2); th.advance_days(56); - let (four_perf_stat, cred4) = th.level_up(&cred3); - credentials.push(cred4); + let (four_perf_stat, _) = th.level_up(&cred3); open_req_size.push(open_perf_stat.req_len as f64); open_req_time.push(open_perf_stat.req_t.as_secs_f64()); open_resp_size.push(open_perf_stat.resp_len as f64); @@ -1435,6 +790,92 @@ fn stats_test_blockage_migration_incremental_and_levels(buckets: u16) { four_resp_size.push(four_perf_stat.resp_len as f64); four_resp_time.push(four_perf_stat.resp_t.as_secs_f64()); four_resp_handle_time.push(four_perf_stat.resp_handle_t.as_secs_f64()); + } + + println!("\n***START: {}*3*2 BUCKETS LEVELS***\n", x); + println!("\n----OPEN-INVITATION-{}---\n", x); + print_stats_test_results( + open_req_size, + open_req_time, + open_resp_size, + open_resp_time, + open_resp_handle_time, + ); + + println!("\n----TRUST-PROMOTION-1: 30 days-{}---\n", x); + print_stats_test_results( + promo_req_size, + promo_req_time, + promo_resp_size, + promo_resp_time, + promo_resp_handle_time, + ); + + println!("\n----TRUST-MIGRATION-0: 30 days-{}---\n", x); + print_stats_test_results( + mig_req_size, + mig_req_time, + mig_resp_size, + mig_resp_time, + mig_resp_handle_time, + ); + + println!("\n----LEVEL-UP-2: 44 days-{}---\n", x); + print_stats_test_results( + sec_req_size, + sec_req_time, + sec_resp_size, + sec_resp_time, + sec_resp_handle_time, + ); + + println!("\n----LEVEL-UP-3: 72 days---{}---\n", x); + print_stats_test_results( + three_req_size, + three_req_time, + three_resp_size, + three_resp_time, + three_resp_handle_time, + ); + + println!("\n----LEVEL-UP-4: 128 days---{}---\n", x); + print_stats_test_results( + four_req_size, + four_req_time, + four_resp_size, + four_resp_time, + four_resp_handle_time, + ); + } +} + +#[test] +fn stats_test_invitations() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + + let mut req_size: Vec = Vec::new(); + let mut resp_size: Vec = Vec::new(); + let mut req_time: Vec = Vec::new(); + let mut resp_time: Vec = Vec::new(); + let mut resp_handle_time: Vec = Vec::new(); + let mut red_req_size: Vec = Vec::new(); + let mut red_resp_size: Vec = Vec::new(); + let mut red_req_time: Vec = Vec::new(); + let mut red_resp_time: Vec = Vec::new(); + let mut red_resp_handle_time: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + th.advance_days(28); + let (perf_stat, (_, invite)) = th.issue_invite(&cred2); + let (bob_perf_stat, _) = th.redeem_invite(&invite); req_size.push(perf_stat.req_len as f64); req_time.push(perf_stat.req_t.as_secs_f64()); resp_size.push(perf_stat.resp_len as f64); @@ -1445,118 +886,560 @@ fn stats_test_blockage_migration_incremental_and_levels(buckets: u16) { red_resp_size.push(bob_perf_stat.resp_len as f64); red_resp_time.push(bob_perf_stat.resp_t.as_secs_f64()); red_resp_handle_time.push(bob_perf_stat.resp_handle_t.as_secs_f64()); - } - println!("\n----WEIRD-OPEN-INVITATION----\n"); - print_stats_test_results( - open_req_size, - open_req_time, - open_resp_size, - open_resp_time, - open_resp_handle_time, - ); - - println!("\n----WEIRD-TRUST-PROMOTION-1: 30 days----\n"); - print_stats_test_results( - promo_req_size, - promo_req_time, - promo_resp_size, - promo_resp_time, - promo_resp_handle_time, - ); - - println!("\n----WEIRD-TRUST-MIGRATION-0: 30 days------------\n"); - print_stats_test_results( - mig_req_size, - mig_req_time, - mig_resp_size, - mig_resp_time, - mig_resp_handle_time, - ); - - println!("\n----WEIRD-LEVEL-UP-2: 44 days----\n"); - print_stats_test_results( - sec_req_size, - sec_req_time, - sec_resp_size, - sec_resp_time, - sec_resp_handle_time, - ); - - println!("\n----WEIRD-LEVEL-UP-3: 72 days------\n"); - print_stats_test_results( - three_req_size, - three_req_time, - three_resp_size, - three_resp_time, - three_resp_handle_time, - ); - - println!("\n----WEIRD-LEVEL-UP-4: 128 days------\n"); - print_stats_test_results( - four_req_size, - four_req_time, - four_resp_size, - four_resp_time, - four_resp_handle_time, - ); - println!("\n----ISSUE-INVITATION----\n"); + println!("\n***START: {}*3*2 BUCKETS INVITATIONS***\n", x); + println!("\n----ISSUE-INVITATION-{}---\n", x); print_stats_test_results(req_size, req_time, resp_size, resp_time, resp_handle_time); - println!("\n----REDEEM-INVITATION----\n"); + + println!("\n----REDEEM-INVITATION-{}---\n", x); print_stats_test_results( - red_req_size, - red_req_time, - red_resp_size, - red_resp_time, - red_resp_handle_time, - ); + red_req_size, + red_req_time, + red_resp_size, + red_resp_time, + red_resp_handle_time, + ); + } +} +#[test] +fn stats_test_blockage_migration_5() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..1000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 5***\n", x); + block_bridges(&mut th, 5, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_10() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..1000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 10***\n", x); block_bridges(&mut th, 10, credentials); } } #[test] -fn test_all(){ +fn stats_test_blockage_migration_15() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { - println!("\n***START: {}*3*2 BUCKETS***\n", x); - stats_test_trust_levels(x); - stats_test_invitations(x); - stats_test_blockage_migration_5(x); - stats_test_blockage_migration_10(x); - stats_test_blockage_migration_15(x); - stats_test_blockage_migration_20(x); - stats_test_blockage_migration_25(x); - stats_test_blockage_migration_30(x); - stats_test_blockage_migration_35(x); - stats_test_blockage_migration_40(x); - stats_test_blockage_migration_45(x); - stats_test_blockage_migration_50(x); - stats_test_blockage_migration_55(x); - stats_test_blockage_migration_60(x); - stats_test_blockage_migration_65(x); - stats_test_blockage_migration_70(x); - stats_test_blockage_migration_75(x); - stats_test_blockage_migration_80(x); - stats_test_blockage_migration_85(x); - stats_test_blockage_migration_90(x); - stats_test_blockage_migration_95(x); - stats_test_blockage_migration_100(x); + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + println!("\n***START: {}*3*2 BUCKETS 15***\n", x); + block_bridges(&mut th, 15, credentials); } +} - let buckets2: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - for x in buckets2 { - println!("\n***START: {}*3*2 BUCKETS FOR WEIRD TEST***\n", x); - stats_test_blockage_migration_incremental_and_levels(x); +#[test] +fn stats_test_blockage_migration_20() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 20***\n", x); + block_bridges(&mut th, 20, credentials); } +} - println!("\nAll done!\n"); +#[test] +fn stats_test_blockage_migration_25() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 25***\n", x); + block_bridges(&mut th, 25, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_30() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 30***\n", x); + block_bridges(&mut th, 30, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_35() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 35***\n", x); + block_bridges(&mut th, 35, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_40() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 40***\n", x); + block_bridges(&mut th, 40, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_45() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 45***\n", x); + block_bridges(&mut th, 45, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_50() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 50***\n", x); + block_bridges(&mut th, 50, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_55() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 55***\n", x); + block_bridges(&mut th, 55, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_60() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 60***\n", x); + block_bridges(&mut th, 60, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_65() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 65***\n", x); + block_bridges(&mut th, 65, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_70() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 70***\n", x); + block_bridges(&mut th, 70, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_75() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 75***\n", x); + block_bridges(&mut th, 75, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_80() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 80***\n", x); + block_bridges(&mut th, 80, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_85() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 85***\n", x); + block_bridges(&mut th, 85, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_90() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 90***\n", x); + block_bridges(&mut th, 90, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_95() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + + println!("\n***START: {}*3*2 BUCKETS 95***\n", x); + block_bridges(&mut th, 95, credentials); + } +} + +#[test] +fn stats_test_blockage_migration_100() { + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + + for x in buckets { + let mut th = TestHarness::new_buckets(x, x); + let mut credentials: Vec = Vec::new(); + for _ in 0..10000 { + let cred = th.open_invite().1 .0; + th.advance_days(30); + let (_, migcred) = th.trust_promotion(&cred); + let (_, cred1) = th.level0_migration(&cred, &migcred); + th.advance_days(14); + let (_, cred2) = th.level_up(&cred1); + let (_, (cred2a, invite)) = th.issue_invite(&cred2); + let (_, bob_cred) = th.redeem_invite(&invite); + th.advance_days(28); + let (_, _) = th.level_up(&bob_cred); + let (_, cred3) = th.level_up(&cred2a); + credentials.push(cred3); + } + println!("\n***START: {}*3*2 BUCKETS 100***\n", x); + block_bridges(&mut th, 100, credentials); + } } /// Blocks a percentage of the bridges for the passed Test Harness @@ -1625,23 +1508,13 @@ fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec Date: Sun, 3 Apr 2022 05:03:35 +0000 Subject: [PATCH 073/115] Added timing --- crates/lox-library/Cargo.toml | 1 + crates/lox-library/src/tests.rs | 235 +++++++++++++++++++++++++------- 2 files changed, 186 insertions(+), 50 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index 3d50805..6b7e6a9 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -10,6 +10,7 @@ ed25519-dalek = "1" # zkp = { version = "0.8", features = ["debug-transcript"] } zkp = "0.8" bincode = "1" +chrono = "0.4" rand = "0.7" serde = "1" serde_with = "1.9.1" diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 17450e2..9fed337 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -4,9 +4,11 @@ BridgeLine::random() or private fields */ use super::bridge_table::BridgeLine; use super::proto::*; use super::*; +use chrono::{Utc, DateTime, NaiveTime, Timelike}; use rand::Rng; use statistical::{mean, standard_deviation}; use std::collections::HashSet; +use std::thread; use std::time::{Duration, Instant}; struct PerfStat { @@ -370,7 +372,7 @@ impl TestHarness { } } -#[test] +//#[test] fn test_open_invite() { let mut th = TestHarness::new(); @@ -391,7 +393,7 @@ fn test_open_invite() { assert!(bridgeline == bucket.0[0]); } -#[test] +//#[test] fn test_trust_promotion() { let mut th = TestHarness::new(); @@ -415,7 +417,7 @@ fn test_trust_promotion() { assert!(th.ba.verify_reachability(&bucket.1.unwrap())); } -#[test] +//#[test] fn test_level0_migration() { let mut th = TestHarness::new(); @@ -446,7 +448,7 @@ fn test_level0_migration() { assert!(th.ba.verify_reachability(&bucket.1.unwrap())); } -#[test] +//#[test] fn test_level_up() { let mut th = TestHarness::new(); @@ -501,7 +503,7 @@ fn test_level_up() { assert!(th.ba.verify_lox(&cred4)); } -#[test] +//#[test] fn test_issue_invite() { let mut th = TestHarness::new(); @@ -541,7 +543,7 @@ fn test_issue_invite() { println!("invite = {:?}", invite); } -#[test] +//#[test] fn test_redeem_invite() { let mut th = TestHarness::new(); @@ -591,7 +593,7 @@ fn test_redeem_invite() { println!("bob_cred = {:?}", bob_cred); } -#[test] +//#[test] fn test_mark_unreachable() { let mut th = TestHarness::new(); @@ -641,7 +643,7 @@ fn test_mark_unreachable() { println!("openinv = {:?}\n", th.bdb.openinv_buckets); } -#[test] +//#[test] fn test_blockage_migration() { let mut th = TestHarness::new(); @@ -712,9 +714,9 @@ fn test_blockage_migration() { assert!(th.ba.verify_lox(&cred4)); } -#[test] +//#[test] fn stats_test_trust_levels() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -750,6 +752,12 @@ fn stats_test_trust_levels() { let mut open_resp_time: Vec = Vec::new(); let mut open_resp_handle_time: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let (open_perf_stat, cred) = th.open_invite(); th.advance_days(30); let (tp_perf_stat, migcred) = th.trust_promotion(&cred.0); @@ -849,9 +857,9 @@ fn stats_test_trust_levels() { } } -#[test] +//#[test] fn stats_test_invitations() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -867,6 +875,13 @@ fn stats_test_invitations() { let mut red_resp_time: Vec = Vec::new(); let mut red_resp_handle_time: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -903,14 +918,20 @@ fn stats_test_invitations() { } } -#[test] +//#[test] fn stats_test_blockage_migration_5() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..1000 { + for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -930,14 +951,20 @@ fn stats_test_blockage_migration_5() { } } -#[test] +//#[test] fn stats_test_blockage_migration_10() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..1000 { + for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -957,14 +984,20 @@ fn stats_test_blockage_migration_10() { } } -#[test] +//#[test] fn stats_test_blockage_migration_15() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -984,14 +1017,20 @@ fn stats_test_blockage_migration_15() { } } -#[test] +//#[test] fn stats_test_blockage_migration_20() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1011,14 +1050,20 @@ fn stats_test_blockage_migration_20() { } } -#[test] +//#[test] fn stats_test_blockage_migration_25() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1038,14 +1083,20 @@ fn stats_test_blockage_migration_25() { } } -#[test] +//#[test] fn stats_test_blockage_migration_30() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1065,14 +1116,20 @@ fn stats_test_blockage_migration_30() { } } -#[test] +//#[test] fn stats_test_blockage_migration_35() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1094,12 +1151,18 @@ fn stats_test_blockage_migration_35() { #[test] fn stats_test_blockage_migration_40() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![900]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1121,12 +1184,18 @@ fn stats_test_blockage_migration_40() { #[test] fn stats_test_blockage_migration_45() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![900]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1148,12 +1217,18 @@ fn stats_test_blockage_migration_45() { #[test] fn stats_test_blockage_migration_50() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1175,12 +1250,18 @@ fn stats_test_blockage_migration_50() { #[test] fn stats_test_blockage_migration_55() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![900]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1200,14 +1281,20 @@ fn stats_test_blockage_migration_55() { } } -#[test] +////#[test] fn stats_test_blockage_migration_60() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1227,14 +1314,20 @@ fn stats_test_blockage_migration_60() { } } -#[test] +//#[test] fn stats_test_blockage_migration_65() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1254,14 +1347,20 @@ fn stats_test_blockage_migration_65() { } } -#[test] +//#[test] fn stats_test_blockage_migration_70() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1281,14 +1380,20 @@ fn stats_test_blockage_migration_70() { } } -#[test] +//#[test] fn stats_test_blockage_migration_75() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1308,14 +1413,20 @@ fn stats_test_blockage_migration_75() { } } -#[test] +//#[test] fn stats_test_blockage_migration_80() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1335,14 +1446,20 @@ fn stats_test_blockage_migration_80() { } } -#[test] +//#[test] fn stats_test_blockage_migration_85() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1362,14 +1479,20 @@ fn stats_test_blockage_migration_85() { } } -#[test] +//#[test] fn stats_test_blockage_migration_90() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1389,14 +1512,20 @@ fn stats_test_blockage_migration_90() { } } -#[test] +//#[test] fn stats_test_blockage_migration_95() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1416,14 +1545,20 @@ fn stats_test_blockage_migration_95() { } } -#[test] +//#[test] fn stats_test_blockage_migration_100() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..10000 { + let h: NaiveTime = DateTime::time(&Utc::now()); + if h.hour() == 23 && h.minute() == 59 { + println!("Biding my time for a minute"); + thread::sleep(Duration::new(60,0)); + println!("Ready to work again"); + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); From a7be6d3bfd5de9c5e3ca5c13c637839a513265bd Mon Sep 17 00:00:00 2001 From: onyinyang Date: Sun, 3 Apr 2022 05:54:53 +0000 Subject: [PATCH 074/115] Added Updated tests file and readme --- crates/lox-library/src/readme.md | 17 ++++ crates/lox-library/src/tests.rs | 150 +++++++++++++++---------------- 2 files changed, 92 insertions(+), 75 deletions(-) create mode 100644 crates/lox-library/src/readme.md diff --git a/crates/lox-library/src/readme.md b/crates/lox-library/src/readme.md new file mode 100644 index 0000000..cf94798 --- /dev/null +++ b/crates/lox-library/src/readme.md @@ -0,0 +1,17 @@ +# 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) + +### To run the tests used for our experimental results: + +``` +cargo test -- --nocapture stats_test > stats_test.log +``` +Note that: our implementation is coded such that the reachability certificate expires at 00:00 UTC. A workaround has been included in each test to pause if it is too close to this time so the request won't fail. 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). + +### To run all Lox tests: + +``` +cargo test -- --nocapture test > testing.log +``` diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 9fed337..08430f1 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -372,7 +372,7 @@ impl TestHarness { } } -//#[test] +#[test] fn test_open_invite() { let mut th = TestHarness::new(); @@ -393,7 +393,7 @@ fn test_open_invite() { assert!(bridgeline == bucket.0[0]); } -//#[test] +#[test] fn test_trust_promotion() { let mut th = TestHarness::new(); @@ -417,7 +417,7 @@ fn test_trust_promotion() { assert!(th.ba.verify_reachability(&bucket.1.unwrap())); } -//#[test] +#[test] fn test_level0_migration() { let mut th = TestHarness::new(); @@ -448,7 +448,7 @@ fn test_level0_migration() { assert!(th.ba.verify_reachability(&bucket.1.unwrap())); } -//#[test] +#[test] fn test_level_up() { let mut th = TestHarness::new(); @@ -503,7 +503,7 @@ fn test_level_up() { assert!(th.ba.verify_lox(&cred4)); } -//#[test] +#[test] fn test_issue_invite() { let mut th = TestHarness::new(); @@ -543,7 +543,7 @@ fn test_issue_invite() { println!("invite = {:?}", invite); } -//#[test] +#[test] fn test_redeem_invite() { let mut th = TestHarness::new(); @@ -593,7 +593,7 @@ fn test_redeem_invite() { println!("bob_cred = {:?}", bob_cred); } -//#[test] +#[test] fn test_mark_unreachable() { let mut th = TestHarness::new(); @@ -643,7 +643,7 @@ fn test_mark_unreachable() { println!("openinv = {:?}\n", th.bdb.openinv_buckets); } -//#[test] +#[test] fn test_blockage_migration() { let mut th = TestHarness::new(); @@ -714,9 +714,9 @@ fn test_blockage_migration() { assert!(th.ba.verify_lox(&cred4)); } -//#[test] +#[test] fn stats_test_trust_levels() { - let buckets: Vec = vec![900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -754,7 +754,7 @@ fn stats_test_trust_levels() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -857,9 +857,9 @@ fn stats_test_trust_levels() { } } -//#[test] +#[test] fn stats_test_invitations() { - let buckets: Vec = vec![1050, 1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -878,7 +878,7 @@ fn stats_test_invitations() { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -918,9 +918,9 @@ fn stats_test_invitations() { } } -//#[test] +#[test] fn stats_test_blockage_migration_5() { - let buckets: Vec = vec![1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -928,7 +928,7 @@ fn stats_test_blockage_migration_5() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -951,9 +951,9 @@ fn stats_test_blockage_migration_5() { } } -//#[test] +#[test] fn stats_test_blockage_migration_10() { - let buckets: Vec = vec![1050, 1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -961,7 +961,7 @@ fn stats_test_blockage_migration_10() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -984,9 +984,9 @@ fn stats_test_blockage_migration_10() { } } -//#[test] +#[test] fn stats_test_blockage_migration_15() { - let buckets: Vec = vec![1050, 1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -994,7 +994,7 @@ fn stats_test_blockage_migration_15() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1017,9 +1017,9 @@ fn stats_test_blockage_migration_15() { } } -//#[test] +#[test] fn stats_test_blockage_migration_20() { - let buckets: Vec = vec![1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1027,7 +1027,7 @@ fn stats_test_blockage_migration_20() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1050,9 +1050,9 @@ fn stats_test_blockage_migration_20() { } } -//#[test] +#[test] fn stats_test_blockage_migration_25() { - let buckets: Vec = vec![1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1060,7 +1060,7 @@ fn stats_test_blockage_migration_25() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1083,9 +1083,9 @@ fn stats_test_blockage_migration_25() { } } -//#[test] +#[test] fn stats_test_blockage_migration_30() { - let buckets: Vec = vec![1050, 1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1093,7 +1093,7 @@ fn stats_test_blockage_migration_30() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1116,9 +1116,9 @@ fn stats_test_blockage_migration_30() { } } -//#[test] +#[test] fn stats_test_blockage_migration_35() { - let buckets: Vec = vec![1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1126,7 +1126,7 @@ fn stats_test_blockage_migration_35() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1151,7 +1151,7 @@ fn stats_test_blockage_migration_35() { #[test] fn stats_test_blockage_migration_40() { - let buckets: Vec = vec![900]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1159,7 +1159,7 @@ fn stats_test_blockage_migration_40() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1184,7 +1184,7 @@ fn stats_test_blockage_migration_40() { #[test] fn stats_test_blockage_migration_45() { - let buckets: Vec = vec![900]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1192,7 +1192,7 @@ fn stats_test_blockage_migration_45() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1217,7 +1217,7 @@ fn stats_test_blockage_migration_45() { #[test] fn stats_test_blockage_migration_50() { - let buckets: Vec = vec![1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1225,7 +1225,7 @@ fn stats_test_blockage_migration_50() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1250,7 +1250,7 @@ fn stats_test_blockage_migration_50() { #[test] fn stats_test_blockage_migration_55() { - let buckets: Vec = vec![900]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1258,7 +1258,7 @@ fn stats_test_blockage_migration_55() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1281,9 +1281,9 @@ fn stats_test_blockage_migration_55() { } } -////#[test] +#[test] fn stats_test_blockage_migration_60() { - let buckets: Vec = vec![1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1291,7 +1291,7 @@ fn stats_test_blockage_migration_60() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1314,9 +1314,9 @@ fn stats_test_blockage_migration_60() { } } -//#[test] +#[test] fn stats_test_blockage_migration_65() { - let buckets: Vec = vec![1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1324,7 +1324,7 @@ fn stats_test_blockage_migration_65() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1347,9 +1347,9 @@ fn stats_test_blockage_migration_65() { } } -//#[test] +#[test] fn stats_test_blockage_migration_70() { - let buckets: Vec = vec![1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1357,7 +1357,7 @@ fn stats_test_blockage_migration_70() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1380,9 +1380,9 @@ fn stats_test_blockage_migration_70() { } } -//#[test] +#[test] fn stats_test_blockage_migration_75() { - let buckets: Vec = vec![1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1390,7 +1390,7 @@ fn stats_test_blockage_migration_75() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1413,9 +1413,9 @@ fn stats_test_blockage_migration_75() { } } -//#[test] +#[test] fn stats_test_blockage_migration_80() { - let buckets: Vec = vec![900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1423,7 +1423,7 @@ fn stats_test_blockage_migration_80() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1446,9 +1446,9 @@ fn stats_test_blockage_migration_80() { } } -//#[test] +#[test] fn stats_test_blockage_migration_85() { - let buckets: Vec = vec![1050, 1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1456,7 +1456,7 @@ fn stats_test_blockage_migration_85() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1479,9 +1479,9 @@ fn stats_test_blockage_migration_85() { } } -//#[test] +#[test] fn stats_test_blockage_migration_90() { - let buckets: Vec = vec![1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1489,7 +1489,7 @@ fn stats_test_blockage_migration_90() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1512,9 +1512,9 @@ fn stats_test_blockage_migration_90() { } } -//#[test] +#[test] fn stats_test_blockage_migration_95() { - let buckets: Vec = vec![1050, 1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1522,7 +1522,7 @@ fn stats_test_blockage_migration_95() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1545,9 +1545,9 @@ fn stats_test_blockage_migration_95() { } } -//#[test] +#[test] fn stats_test_blockage_migration_100() { - let buckets: Vec = vec![750, 900, 1050, 1200, 1350, 1500]; + let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { let mut th = TestHarness::new_buckets(x, x); @@ -1555,7 +1555,7 @@ fn stats_test_blockage_migration_100() { for _ in 0..10000 { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { - println!("Biding my time for a minute"); + println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); } @@ -1667,11 +1667,11 @@ fn print_test_results(perf_stat: PerfStat) { println!("Response handle time = {:?}", perf_stat.resp_handle_t); } -fn print_time_test_results(perf_stat: PerfStat) { - println!("Request time = {:?}", perf_stat.req_t); - println!("Response time = {:?}", perf_stat.resp_t); - println!("Response handle time = {:?}", perf_stat.resp_handle_t); -} +//fn print_time_test_results(perf_stat: PerfStat) { +// println!("Request time = {:?}", perf_stat.req_t); +// println!("Response time = {:?}", perf_stat.resp_t); +// println!("Response handle time = {:?}", perf_stat.resp_handle_t); +//} fn print_stats_test_results( req_size: Vec, From 1fe1c147ab7f15db402c4ce1eb99a63dea712b7e Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 4 Apr 2022 00:42:20 -0400 Subject: [PATCH 075/115] Moved README and fixed substring issue --- .../lox-library/{src/readme.md => README.md} | 4 +- crates/lox-library/src/tests.rs | 84 +++++++++---------- 2 files changed, 44 insertions(+), 44 deletions(-) rename crates/lox-library/{src/readme.md => README.md} (86%) diff --git a/crates/lox-library/src/readme.md b/crates/lox-library/README.md similarity index 86% rename from crates/lox-library/src/readme.md rename to crates/lox-library/README.md index cf94798..b77d5f3 100644 --- a/crates/lox-library/src/readme.md +++ b/crates/lox-library/README.md @@ -6,12 +6,12 @@ Lox is written in rust and requires `cargo` to test. [Install Rust](https://www. ### To run the tests used for our experimental results: ``` -cargo test -- --nocapture stats_test > stats_test.log +cargo test --release -- --nocapture stats_test > stats_test.log ``` Note that: our implementation is coded such that the reachability certificate expires at 00:00 UTC. A workaround has been included in each test to pause if it is too close to this time so the request won't fail. 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). ### To run all Lox tests: ``` -cargo test -- --nocapture test > testing.log +cargo test --release -- --nocapture test > testing.log ``` diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 08430f1..ace57db 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -757,7 +757,7 @@ fn stats_test_trust_levels() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let (open_perf_stat, cred) = th.open_invite(); th.advance_days(30); let (tp_perf_stat, migcred) = th.trust_promotion(&cred.0); @@ -881,7 +881,7 @@ fn stats_test_invitations() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -919,7 +919,7 @@ fn stats_test_invitations() { } #[test] -fn stats_test_blockage_migration_5() { +fn stats_test_percent_blockage_migration_5() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -931,7 +931,7 @@ fn stats_test_blockage_migration_5() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -952,7 +952,7 @@ fn stats_test_blockage_migration_5() { } #[test] -fn stats_test_blockage_migration_10() { +fn stats_test_percent_blockage_migration_10() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -964,7 +964,7 @@ fn stats_test_blockage_migration_10() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -985,7 +985,7 @@ fn stats_test_blockage_migration_10() { } #[test] -fn stats_test_blockage_migration_15() { +fn stats_test_percent_blockage_migration_15() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -997,7 +997,7 @@ fn stats_test_blockage_migration_15() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1018,7 +1018,7 @@ fn stats_test_blockage_migration_15() { } #[test] -fn stats_test_blockage_migration_20() { +fn stats_test_percent_blockage_migration_20() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1030,7 +1030,7 @@ fn stats_test_blockage_migration_20() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1051,7 +1051,7 @@ fn stats_test_blockage_migration_20() { } #[test] -fn stats_test_blockage_migration_25() { +fn stats_test_percent_blockage_migration_25() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1063,7 +1063,7 @@ fn stats_test_blockage_migration_25() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1084,7 +1084,7 @@ fn stats_test_blockage_migration_25() { } #[test] -fn stats_test_blockage_migration_30() { +fn stats_test_percent_blockage_migration_30() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1096,7 +1096,7 @@ fn stats_test_blockage_migration_30() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1117,7 +1117,7 @@ fn stats_test_blockage_migration_30() { } #[test] -fn stats_test_blockage_migration_35() { +fn stats_test_percent_blockage_migration_35() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1129,7 +1129,7 @@ fn stats_test_blockage_migration_35() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1150,7 +1150,7 @@ fn stats_test_blockage_migration_35() { } #[test] -fn stats_test_blockage_migration_40() { +fn stats_test_percent_blockage_migration_40() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1162,7 +1162,7 @@ fn stats_test_blockage_migration_40() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1183,7 +1183,7 @@ fn stats_test_blockage_migration_40() { } #[test] -fn stats_test_blockage_migration_45() { +fn stats_test_percent_blockage_migration_45() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1195,7 +1195,7 @@ fn stats_test_blockage_migration_45() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1216,7 +1216,7 @@ fn stats_test_blockage_migration_45() { } #[test] -fn stats_test_blockage_migration_50() { +fn stats_test_percent_blockage_migration_50() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1228,7 +1228,7 @@ fn stats_test_blockage_migration_50() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1249,7 +1249,7 @@ fn stats_test_blockage_migration_50() { } #[test] -fn stats_test_blockage_migration_55() { +fn stats_test_percent_blockage_migration_55() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1261,7 +1261,7 @@ fn stats_test_blockage_migration_55() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1282,7 +1282,7 @@ fn stats_test_blockage_migration_55() { } #[test] -fn stats_test_blockage_migration_60() { +fn stats_test_percent_blockage_migration_60() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1294,7 +1294,7 @@ fn stats_test_blockage_migration_60() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1315,7 +1315,7 @@ fn stats_test_blockage_migration_60() { } #[test] -fn stats_test_blockage_migration_65() { +fn stats_test_percent_blockage_migration_65() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1327,7 +1327,7 @@ fn stats_test_blockage_migration_65() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1348,7 +1348,7 @@ fn stats_test_blockage_migration_65() { } #[test] -fn stats_test_blockage_migration_70() { +fn stats_test_percent_blockage_migration_70() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1360,7 +1360,7 @@ fn stats_test_blockage_migration_70() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1381,7 +1381,7 @@ fn stats_test_blockage_migration_70() { } #[test] -fn stats_test_blockage_migration_75() { +fn stats_test_percent_blockage_migration_75() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1393,7 +1393,7 @@ fn stats_test_blockage_migration_75() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1414,7 +1414,7 @@ fn stats_test_blockage_migration_75() { } #[test] -fn stats_test_blockage_migration_80() { +fn stats_test_percent_blockage_migration_80() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1426,7 +1426,7 @@ fn stats_test_blockage_migration_80() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1447,7 +1447,7 @@ fn stats_test_blockage_migration_80() { } #[test] -fn stats_test_blockage_migration_85() { +fn stats_test_percent_blockage_migration_85() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1459,7 +1459,7 @@ fn stats_test_blockage_migration_85() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1480,7 +1480,7 @@ fn stats_test_blockage_migration_85() { } #[test] -fn stats_test_blockage_migration_90() { +fn stats_test_percent_blockage_migration_90() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1492,7 +1492,7 @@ fn stats_test_blockage_migration_90() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1513,7 +1513,7 @@ fn stats_test_blockage_migration_90() { } #[test] -fn stats_test_blockage_migration_95() { +fn stats_test_percent_blockage_migration_95() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1525,7 +1525,7 @@ fn stats_test_blockage_migration_95() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); @@ -1546,7 +1546,7 @@ fn stats_test_blockage_migration_95() { } #[test] -fn stats_test_blockage_migration_100() { +fn stats_test_percent_blockage_migration_100() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -1558,7 +1558,7 @@ fn stats_test_blockage_migration_100() { println!("Wait for UTC 00:00"); thread::sleep(Duration::new(60,0)); println!("Ready to work again"); - } + } let cred = th.open_invite().1 .0; th.advance_days(30); let (_, migcred) = th.trust_promotion(&cred); From 666cfd4582fa1e6ed63c397319ee3f809040f444 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 4 Apr 2022 13:22:51 -0400 Subject: [PATCH 076/115] Fixed testing instructions and another substring issue --- crates/lox-library/README.md | 37 ++++++++++++++++++++++++++------- crates/lox-library/src/tests.rs | 4 ++-- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/crates/lox-library/README.md b/crates/lox-library/README.md index b77d5f3..f3cc566 100644 --- a/crates/lox-library/README.md +++ b/crates/lox-library/README.md @@ -3,15 +3,38 @@ 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) -### To run the tests used for our experimental results: +### To run the tests used for our experimental results run: ``` -cargo test --release -- --nocapture stats_test > stats_test.log +cargo test --release -- --nocapture TESTNAME ``` + +Where TESTNAME is one of: + +``` +stats_test_trust_levels +stats_test_invitations +stats_test_percent_blockage_migration_05 +stats_test_percent_blockage_migration_010 +stats_test_percent_blockage_migration_15 +stats_test_percent_blockage_migration_20 +stats_test_percent_blockage_migration_25 +stats_test_percent_blockage_migration_30 +stats_test_percent_blockage_migration_35 +stats_test_percent_blockage_migration_40 +stats_test_percent_blockage_migration_45 +stats_test_percent_blockage_migration_50 +stats_test_percent_blockage_migration_55 +stats_test_percent_blockage_migration_60 +stats_test_percent_blockage_migration_65 +stats_test_percent_blockage_migration_70 +stats_test_percent_blockage_migration_75 +stats_test_percent_blockage_migration_80 +stats_test_percent_blockage_migration_85 +stats_test_percent_blockage_migration_90 +stats_test_percent_blockage_migration_95 +stats_test_percent_blockage_migration_100 +``` + Note that: our implementation is coded such that the reachability certificate expires at 00:00 UTC. A workaround has been included in each test to pause if it is too close to this time so the request won't fail. 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). -### To run all Lox tests: - -``` -cargo test --release -- --nocapture test > testing.log -``` diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index ace57db..1766ed4 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -919,7 +919,7 @@ fn stats_test_invitations() { } #[test] -fn stats_test_percent_blockage_migration_5() { +fn stats_test_percent_blockage_migration_05() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { @@ -952,7 +952,7 @@ fn stats_test_percent_blockage_migration_5() { } #[test] -fn stats_test_percent_blockage_migration_10() { +fn stats_test_percent_blockage_migration_010() { let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; for x in buckets { From 90d19b98460929c48bae5c24b3ee8f08181b1a6e Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 6 Apr 2022 18:29:11 -0400 Subject: [PATCH 077/115] Added times to readme --- crates/lox-library/README.md | 50 +++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/crates/lox-library/README.md b/crates/lox-library/README.md index f3cc566..b65463e 100644 --- a/crates/lox-library/README.md +++ b/crates/lox-library/README.md @@ -11,30 +11,32 @@ cargo test --release -- --nocapture TESTNAME Where TESTNAME is one of: -``` -stats_test_trust_levels -stats_test_invitations -stats_test_percent_blockage_migration_05 -stats_test_percent_blockage_migration_010 -stats_test_percent_blockage_migration_15 -stats_test_percent_blockage_migration_20 -stats_test_percent_blockage_migration_25 -stats_test_percent_blockage_migration_30 -stats_test_percent_blockage_migration_35 -stats_test_percent_blockage_migration_40 -stats_test_percent_blockage_migration_45 -stats_test_percent_blockage_migration_50 -stats_test_percent_blockage_migration_55 -stats_test_percent_blockage_migration_60 -stats_test_percent_blockage_migration_65 -stats_test_percent_blockage_migration_70 -stats_test_percent_blockage_migration_75 -stats_test_percent_blockage_migration_80 -stats_test_percent_blockage_migration_85 -stats_test_percent_blockage_migration_90 -stats_test_percent_blockage_migration_95 -stats_test_percent_blockage_migration_100 -``` +| TESTNAME | Run Time (m)| +|------|-------| +| stats_test_trust_levels | 1716.15499 | +| stats_test_invitations | 1379.40724 | +| stats_test_percent_blockage_migration_05 | 1487.23794 | +| stats_test_percent_blockage_migration_010 | 1489.58697 | +| stats_test_percent_blockage_migration_15 | 1496.0887 | +| stats_test_percent_blockage_migration_20 | 1506.3363 | +| stats_test_percent_blockage_migration_25 | 1505.42065 | +| stats_test_percent_blockage_migration_30 | 1517.29230 | +| stats_test_percent_blockage_migration_35 | 1520.33539 | +| stats_test_percent_blockage_migration_40 | 1530.58220 | +| stats_test_percent_blockage_migration_45 | 1542.31211 | +| stats_test_percent_blockage_migration_50 | 1556.33415 | +| stats_test_percent_blockage_migration_55 | 1562.36914 | +| stats_test_percent_blockage_migration_60 | 1575.24665 | +| stats_test_percent_blockage_migration_65 | 1589.46323 | +| stats_test_percent_blockage_migration_70 | 1604.29720 | +| stats_test_percent_blockage_migration_75 | 1621.36433 | +| stats_test_percent_blockage_migration_80 | 1634.56597 | +| stats_test_percent_blockage_migration_85 | 1652.31102 | +| stats_test_percent_blockage_migration_90 | 1670.11576 | +| stats_test_percent_blockage_migration_95 | 1691.54106 | +| stats_test_percent_blockage_migration_100 | 1709.28131 | + Note that: our implementation is coded such that the reachability certificate expires at 00:00 UTC. A workaround has been included in each test to pause if it is too close to this time so the request won't fail. 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). + From 45b53590f7ea2ca54f68998a823a2ba0cb9eb200 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 6 Apr 2022 22:33:36 -0400 Subject: [PATCH 078/115] Removed table --- crates/lox-library/README.md | 49 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/crates/lox-library/README.md b/crates/lox-library/README.md index b65463e..bf36ffe 100644 --- a/crates/lox-library/README.md +++ b/crates/lox-library/README.md @@ -11,31 +11,32 @@ cargo test --release -- --nocapture TESTNAME Where TESTNAME is one of: -| TESTNAME | Run Time (m)| -|------|-------| -| stats_test_trust_levels | 1716.15499 | -| stats_test_invitations | 1379.40724 | -| stats_test_percent_blockage_migration_05 | 1487.23794 | -| stats_test_percent_blockage_migration_010 | 1489.58697 | -| stats_test_percent_blockage_migration_15 | 1496.0887 | -| stats_test_percent_blockage_migration_20 | 1506.3363 | -| stats_test_percent_blockage_migration_25 | 1505.42065 | -| stats_test_percent_blockage_migration_30 | 1517.29230 | -| stats_test_percent_blockage_migration_35 | 1520.33539 | -| stats_test_percent_blockage_migration_40 | 1530.58220 | -| stats_test_percent_blockage_migration_45 | 1542.31211 | -| stats_test_percent_blockage_migration_50 | 1556.33415 | -| stats_test_percent_blockage_migration_55 | 1562.36914 | -| stats_test_percent_blockage_migration_60 | 1575.24665 | -| stats_test_percent_blockage_migration_65 | 1589.46323 | -| stats_test_percent_blockage_migration_70 | 1604.29720 | -| stats_test_percent_blockage_migration_75 | 1621.36433 | -| stats_test_percent_blockage_migration_80 | 1634.56597 | -| stats_test_percent_blockage_migration_85 | 1652.31102 | -| stats_test_percent_blockage_migration_90 | 1670.11576 | -| stats_test_percent_blockage_migration_95 | 1691.54106 | -| stats_test_percent_blockage_migration_100 | 1709.28131 | +``` +stats_test_trust_levels +stats_test_invitations +stats_test_percent_blockage_migration_05 +stats_test_percent_blockage_migration_010 +stats_test_percent_blockage_migration_15 +stats_test_percent_blockage_migration_20 +stats_test_percent_blockage_migration_25 +stats_test_percent_blockage_migration_30 +stats_test_percent_blockage_migration_35 +stats_test_percent_blockage_migration_40 +stats_test_percent_blockage_migration_45 +stats_test_percent_blockage_migration_50 +stats_test_percent_blockage_migration_55 +stats_test_percent_blockage_migration_60 +stats_test_percent_blockage_migration_65 +stats_test_percent_blockage_migration_70 +stats_test_percent_blockage_migration_75 +stats_test_percent_blockage_migration_80 +stats_test_percent_blockage_migration_85 +stats_test_percent_blockage_migration_90 +stats_test_percent_blockage_migration_95 +stats_test_percent_blockage_migration_100 +``` +Each test takes approximately 20-30 hours to run. Note that: our implementation is coded such that the reachability certificate expires at 00:00 UTC. A workaround has been included in each test to pause if it is too close to this time so the request won't fail. 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). From 203e17f9fa383fed3ce54f76c110da01dbd3adbc Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 6 Apr 2022 22:37:21 -0400 Subject: [PATCH 079/115] Changed format of TESTNAME --- crates/lox-library/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lox-library/README.md b/crates/lox-library/README.md index bf36ffe..c5aad0b 100644 --- a/crates/lox-library/README.md +++ b/crates/lox-library/README.md @@ -9,7 +9,7 @@ Lox is written in rust and requires `cargo` to test. [Install Rust](https://www. cargo test --release -- --nocapture TESTNAME ``` -Where TESTNAME is one of: +Where `TESTNAME` is one of: ``` stats_test_trust_levels From 3dde20d845e32ef16d8b9c4c9621c58605483cf3 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Sun, 14 Aug 2022 20:31:09 -0400 Subject: [PATCH 080/115] Added Dockerfile and build scripts for PETS2023 --- crates/lox-library/Dockerfile | 10 ++++++++++ crates/lox-library/build-lox.sh | 3 +++ crates/lox-library/run-lox.sh | 2 ++ crates/lox-library/stop-lox.sh | 2 ++ 4 files changed, 17 insertions(+) create mode 100644 crates/lox-library/Dockerfile create mode 100755 crates/lox-library/build-lox.sh create mode 100755 crates/lox-library/run-lox.sh create mode 100755 crates/lox-library/stop-lox.sh diff --git a/crates/lox-library/Dockerfile b/crates/lox-library/Dockerfile new file mode 100644 index 0000000..fab6196 --- /dev/null +++ b/crates/lox-library/Dockerfile @@ -0,0 +1,10 @@ +FROM rust:1.56.0 +WORKDIR /home/lox +ADD src/ ./src/ +ADD Cargo.toml Cargo.toml +ADD tests/ ./tests/tests +ADD README.md README.md +RUN cargo build +ENV SHELL=/bin/bash + + diff --git a/crates/lox-library/build-lox.sh b/crates/lox-library/build-lox.sh new file mode 100755 index 0000000..c640c26 --- /dev/null +++ b/crates/lox-library/build-lox.sh @@ -0,0 +1,3 @@ +#!/bin/bash +docker rm lox 2>&1; +docker build -t lox . diff --git a/crates/lox-library/run-lox.sh b/crates/lox-library/run-lox.sh new file mode 100755 index 0000000..67c7e9b --- /dev/null +++ b/crates/lox-library/run-lox.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker run -it lox /bin/bash diff --git a/crates/lox-library/stop-lox.sh b/crates/lox-library/stop-lox.sh new file mode 100755 index 0000000..1383113 --- /dev/null +++ b/crates/lox-library/stop-lox.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker stop lox From cef13f9b079c7050d931e0aa0bc16238feee35e3 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 17 Aug 2022 01:53:10 -0400 Subject: [PATCH 081/115] Updated run script to name container --- crates/lox-library/run-lox.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lox-library/run-lox.sh b/crates/lox-library/run-lox.sh index 67c7e9b..19ca983 100755 --- a/crates/lox-library/run-lox.sh +++ b/crates/lox-library/run-lox.sh @@ -1,2 +1,2 @@ #!/bin/bash -docker run -it lox /bin/bash +docker run --name lox -it lox:latest /bin/bash From 92fb283bcd585753cd13e68aecd6459803fbbbd0 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Wed, 17 Aug 2022 10:20:12 -0400 Subject: [PATCH 082/115] Touch up the docker environment --- crates/lox-library/Dockerfile | 6 ++---- crates/lox-library/README.md | 7 +++++++ crates/lox-library/build-lox.sh | 1 - crates/lox-library/run-lox.sh | 2 +- crates/lox-library/stop-lox.sh | 2 -- 5 files changed, 10 insertions(+), 8 deletions(-) delete mode 100755 crates/lox-library/stop-lox.sh diff --git a/crates/lox-library/Dockerfile b/crates/lox-library/Dockerfile index fab6196..1c12288 100644 --- a/crates/lox-library/Dockerfile +++ b/crates/lox-library/Dockerfile @@ -2,9 +2,7 @@ FROM rust:1.56.0 WORKDIR /home/lox ADD src/ ./src/ ADD Cargo.toml Cargo.toml -ADD tests/ ./tests/tests +ADD tests/ ./tests/ ADD README.md README.md -RUN cargo build +RUN cargo build --release ENV SHELL=/bin/bash - - diff --git a/crates/lox-library/README.md b/crates/lox-library/README.md index c5aad0b..a4e08f3 100644 --- a/crates/lox-library/README.md +++ b/crates/lox-library/README.md @@ -3,6 +3,13 @@ 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) +### To use the docker environment to build the package: + +``` +./build-lox.sh +./run-lox.sh +``` + ### To run the tests used for our experimental results run: ``` diff --git a/crates/lox-library/build-lox.sh b/crates/lox-library/build-lox.sh index c640c26..141dda5 100755 --- a/crates/lox-library/build-lox.sh +++ b/crates/lox-library/build-lox.sh @@ -1,3 +1,2 @@ #!/bin/bash -docker rm lox 2>&1; docker build -t lox . diff --git a/crates/lox-library/run-lox.sh b/crates/lox-library/run-lox.sh index 19ca983..e95657d 100755 --- a/crates/lox-library/run-lox.sh +++ b/crates/lox-library/run-lox.sh @@ -1,2 +1,2 @@ #!/bin/bash -docker run --name lox -it lox:latest /bin/bash +docker run --name lox --rm -it lox:latest /bin/bash diff --git a/crates/lox-library/stop-lox.sh b/crates/lox-library/stop-lox.sh deleted file mode 100755 index 1383113..0000000 --- a/crates/lox-library/stop-lox.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -docker stop lox From 9778f9cd25d2a7913029fc72b249017e96ed4207 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Tue, 11 Oct 2022 02:46:04 -0400 Subject: [PATCH 083/115] Proposed changes for artifact, run_tests_fast feature runs with 100 users --- crates/lox-library/Cargo.toml | 1 + crates/lox-library/Dockerfile | 7 + .../lox-library/Parsing-results/blockages.py | 60 ++++++ .../Parsing-results/check_blockages.py | 110 +++++++++++ .../Parsing-results/make_steady.py | 79 ++++++++ .../Parsing-results/make_tables.py | 68 +++++++ .../lox-library/Parsing-results/parse_data.sh | 14 ++ .../Parsing-results/performance.py | 63 +++++++ .../lox-library/Parsing-results/pets_plots.py | 62 ++++++ .../lox-library/Parsing-results/raw_to_csv.py | 176 ++++++++++++++++++ .../Parsing-results/trust_promo.py | 86 +++++++++ .../Parsing-results/trust_promo_plot.py | 74 ++++++++ crates/lox-library/README.md | 27 ++- crates/lox-library/run_tests_fast.sh | 29 +++ crates/lox-library/src/tests.rs | 49 ++--- 15 files changed, 877 insertions(+), 28 deletions(-) create mode 100644 crates/lox-library/Parsing-results/blockages.py create mode 100644 crates/lox-library/Parsing-results/check_blockages.py create mode 100644 crates/lox-library/Parsing-results/make_steady.py create mode 100644 crates/lox-library/Parsing-results/make_tables.py create mode 100755 crates/lox-library/Parsing-results/parse_data.sh create mode 100644 crates/lox-library/Parsing-results/performance.py create mode 100644 crates/lox-library/Parsing-results/pets_plots.py create mode 100644 crates/lox-library/Parsing-results/raw_to_csv.py create mode 100644 crates/lox-library/Parsing-results/trust_promo.py create mode 100644 crates/lox-library/Parsing-results/trust_promo_plot.py create mode 100755 crates/lox-library/run_tests_fast.sh diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index 6b7e6a9..ea76d76 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -28,3 +28,4 @@ default = ["u64_backend"] u32_backend = ["curve25519-dalek/u32_backend"] u64_backend = ["curve25519-dalek/u64_backend"] simd_backend = ["curve25519-dalek/simd_backend"] +fast = [] diff --git a/crates/lox-library/Dockerfile b/crates/lox-library/Dockerfile index 1c12288..35f7a44 100644 --- a/crates/lox-library/Dockerfile +++ b/crates/lox-library/Dockerfile @@ -3,6 +3,13 @@ WORKDIR /home/lox ADD src/ ./src/ ADD Cargo.toml Cargo.toml ADD tests/ ./tests/ +ADD run_tests_fast.sh . +ADD Parsing-results ./Parsing-results ADD README.md README.md +RUN apt-get update -y +RUN apt-get install -y python3 python3-pip +RUN pip3 install pandas +RUN pip3 install numpy +RUN pip3 install matplotlib RUN cargo build --release ENV SHELL=/bin/bash diff --git a/crates/lox-library/Parsing-results/blockages.py b/crates/lox-library/Parsing-results/blockages.py new file mode 100644 index 0000000..6da60c4 --- /dev/null +++ b/crates/lox-library/Parsing-results/blockages.py @@ -0,0 +1,60 @@ +import pandas as pd +import matplotlib.pyplot as plt +from matplotlib.lines import Line2D + +fig, (axs, axs1) = plt.subplots(2, 4, figsize=(24, 12)) +fig.suptitle("Checking for Blockage and Migration to new Bridges for" + + " Percentage of Bridges Blocked") +columns = ["Percent", "RequestT", "Rtstdev", "ResponseS", "ResponseT", + "ReTstdev", "ResponseHT", "RHTstdev"] +df = pd.read_csv("check_blockage.csv", usecols=columns) +df1 = pd.read_csv("migration.csv", usecols=columns) +fig.supxlabel('Blocked Bridges (%)') +axs[0].set_ylabel('Request Time (ms)') +axs[0].set_ylim([0,70]) +l1 = axs[0].plot(df.Percent, df.RequestT, color='#CC4F1B', + label='Request Time for Percentage of Bridges Blocked') +axs[0].fill_between(df.Percent, df.RequestT-df.Rtstdev, df.RequestT+df.Rtstdev, + alpha=0.5, edgecolor='#CC4F1B', facecolor='#FF9848') +axs1[0].set_ylabel('Request Time (ms)') +axs1[0].set_ylim([0,70]) +axs1[0].plot(df1.Percent, df1.RequestT, color='#1B2ACC', + label='Request Time for Percentage of Bridges Blocked') +axs1[0].fill_between(df1.Percent, df1.RequestT-df1.Rtstdev, + df1.RequestT+df1.Rtstdev, alpha=0.2, edgecolor='#1B2ACC', + facecolor='#089FFF') +axs[1].set_ylabel('Response Time (ms)') +axs[1].plot(df.Percent, df.ResponseT, color='#CC4F1B', + label='Response Time for Percentage of Bridges Blocked') +axs[1].fill_between(df.Percent, df.ResponseT-df.ReTstdev, + df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#CC4F1B', + facecolor='#FF9848') +axs1[1].set_ylabel('Response Time (ms)') +axs1[1].set_ylim([0,70]) +axs1[1].plot(df1.Percent, df1.ResponseT, color='#1B2ACC', + label='Response Time for Percentage of Bridges Blocked') +axs1[1].fill_between(df1.Percent, df1.ResponseT-df1.ReTstdev, + df1.ResponseT+df1.ReTstdev, alpha=0.2, edgecolor='#1B2ACC', + facecolor='#089FFF') +axs[2].set_ylabel('Response Size (ms)') +axs[2].plot(df.Percent, df.ResponseS, color='#CC4F1B', + label='Response Size for Percentage of Bridges Blocked') +axs1[2].set_ylabel('Response Size (ms)') +axs1[2].plot(df1.Percent, df1.ResponseS, color='#1B2ACC', + label='Response Size for Percentage of Bridges Blocked') +axs[3].set_ylabel('Response Handling Time (ms)') +axs[3].plot(df.Percent, df.ResponseHT, color='#CC4F1B', + label='Response Handling Time for Percentage of Bridges Blocked') +axs[3].fill_between(df.Percent, df.ResponseHT-df.RHTstdev, + df.ResponseHT+df.RHTstdev, alpha=0.5, edgecolor='#CC4F1B', + facecolor='#FF9848') +axs1[3].set_ylabel('Response Handling Time (ms)') +axs1[3].set_ylim([0,70]) +axs1[3].plot(df1.Percent, df1.ResponseHT, color='#1B2ACC', + label='Response Handling Time for Percentage of Bridges Blocked') +axs1[3].fill_between(df1.Percent, df1.ResponseHT-df1.RHTstdev, + df1.ResponseHT+df1.RHTstdev, alpha=0.2, edgecolor='#1B2ACC', + facecolor='#089FFF') +legend_elements = [Line2D([0], [0], color='#CC4F1B', label="Check Blockage Protocol"), Line2D([0], [0], color='#1B2ACC', label="Blockage Migration Protocol")] +fig.legend(handles=legend_elements, loc='lower right') +fig.savefig("Performance.pdf") diff --git a/crates/lox-library/Parsing-results/check_blockages.py b/crates/lox-library/Parsing-results/check_blockages.py new file mode 100644 index 0000000..4e820c6 --- /dev/null +++ b/crates/lox-library/Parsing-results/check_blockages.py @@ -0,0 +1,110 @@ +import sys +import pandas as pd +import matplotlib +import matplotlib.pyplot as plt +from matplotlib.lines import Line2D + + +def main(): + + fig, axs = plt.subplots(1, 3, figsize=(24, 7)) + columns = ["Percent","Bridges", "RequestT", "Rtstdev", "ResponseS", "ResponseT", + "ReTstdev", "ResponseHT", "RHTstdev"] + df = pd.read_csv("standard_check"+".csv", usecols=columns) + df.sort_values(["Percent"], axis=0,ascending=[False], inplace=True) + bridges = df.Bridges*2*3 + fig.supxlabel('Blocked Bridges (%)', size=30) + axs[0].set_ylabel('Response Time (ms)', size=25) + axs[0].tick_params(axis='x', labelsize=15) + axs[0].tick_params(axis='y', labelsize=15) +# axs[0].set_xticklabels('Blocked Bridges (%)',fontsize=10) + axs[0].plot(df.Percent, df.ResponseT, color='#CC4F1B', + label='Response Time for Percentage of Bridges Blocked') + axs[0].fill_between(df.Percent, df.ResponseT-df.ReTstdev, + df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#CC4F1B', + facecolor='#FF9848') + axs[1].set_ylabel('Response Size (bytes)', size=25) + axs[1].tick_params(axis='x', labelsize=15) + axs[1].tick_params(axis='y', labelsize=15) + axs[1].plot(df.Percent, df.ResponseS, color='#CC4F1B', + label='Response Size for Percentage of Bridges Blocked') + axs[2].set_ylabel('Response Handling Time (ms)', size=25) + axs[2].tick_params(axis='x', labelsize=15) + axs[2].tick_params(axis='y', labelsize=15) + axs[2].plot(df.Percent, df.ResponseHT, color='#CC4F1B', + label='Response Handling Time for Percentage of Bridges Blocked') + axs[2].fill_between(df.Percent, df.ResponseHT-df.RHTstdev, + df.ResponseHT+df.RHTstdev, alpha=0.5, edgecolor='#CC4F1B', + facecolor='#FF9848') + fig. tight_layout(pad=1) + fig.savefig("StandardCheck.pdf") + plt.close('all') + + for n in range(5,105,5): + fig, axs = plt.subplots(1, 3, figsize=(24, 7)) + columns = ["Percent","Bridges", "RequestT", "Rtstdev", "ResponseS", "ResponseT", + "ReTstdev", "ResponseHT", "RHTstdev"] + df = pd.read_csv("checkblockage"+str(n)+".csv", usecols=columns) + bridges = df.Bridges*2*3 + fig.supxlabel('Total Size of Bridge Pool ('+str(n)+'% Bridges Blocked)',size=30) + axs[0].set_ylabel('Response Time (ms)', size=25) + axs[0].tick_params(axis='x', labelsize=15) + axs[0].tick_params(axis='y', labelsize=15) + axs[0].plot(bridges, df.ResponseT, color='#740202', + label='Response Time for Percentage of Bridges Blocked') + axs[0].fill_between(bridges, df.ResponseT-df.ReTstdev, + df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#740202', + facecolor='#E75252') + axs[1].set_ylabel('Response Size (bytes)', size=25) + axs[1].tick_params(axis='x', labelsize=15) + axs[1].tick_params(axis='y', labelsize=15) + axs[1].plot(bridges, df.ResponseS, color='#740202', + label='Response Size for Percentage of Bridges Blocked') + axs[2].set_ylabel('Response Handling Time (ms)', size=25) + axs[2].tick_params(axis='x', labelsize=15) + axs[2].tick_params(axis='y', labelsize=15) + axs[2].plot(bridges, df.ResponseHT, color='#740202', + label='Response Handling Time for Percentage of Bridges Blocked') + axs[2].fill_between(bridges, df.ResponseHT-df.RHTstdev, + df.ResponseHT+df.RHTstdev, alpha=0.5, edgecolor='#740202', + facecolor='#E75252') + fig. tight_layout(pad=1) + fig.savefig("PerformanceVaried"+str(n)+".pdf") + print("\nDone PerformanceVaried"+str(n)+" Plot.\nOutput to: PerformanceVaried"+str(n)+".pdf") + plt.close('all') + + +def set_plot_options(): + options = { + 'font.size': 12, + 'figure.figsize': (4,2), + 'figure.dpi': 100.0, + 'figure.subplot.left': 0.20, + 'figure.subplot.right': 0.97, + 'figure.subplot.bottom': 0.20, + 'figure.subplot.top': 0.90, + 'grid.color': '0.1', + 'grid.linestyle': ':', + #'grid.linewidth': 0.5, + 'axes.grid' : True, + #'axes.grid.axis' : 'y', + #'axes.axisbelow': True, + 'axes.titlesize' : 25, + 'axes.labelsize' : 25, + 'axes.formatter.limits': (-4,4), + 'xtick.labelsize' : 30,#get_tick_font_size_10(), + 'ytick.labelsize' : 30,#get_tick_font_size_10(), + 'lines.linewidth' : 2.0, + 'lines.markeredgewidth' : 0.5, + 'lines.markersize' : 15, + } + + for option_key in options: + matplotlib.rcParams[option_key] = options[option_key] + if 'figure.max_num_figures' in matplotlib.rcParams: + matplotlib.rcParams['figure.max_num_figures'] = 100 + if 'figure.max_open_warning' in matplotlib.rcParams: + matplotlib.rcParams['figure.max_open_warning'] = 100 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/crates/lox-library/Parsing-results/make_steady.py b/crates/lox-library/Parsing-results/make_steady.py new file mode 100644 index 0000000..674dfee --- /dev/null +++ b/crates/lox-library/Parsing-results/make_steady.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +import sys +import json +import lzma +import numpy as np + +import matplotlib +import matplotlib.pyplot as pyplot +import matplotlib.colors as mcolors + + +def main(): + set_plot_options() + buckets = [600, 1200, 1800, 2400, 3000] + n = 1000000 + ft = [] + + pyplot.figure() + for b in buckets: + delta = np.arange(1/10,1,.01) + x = [] + for d in delta: + p = n*(1.61 + (14.71/d+23.725/d**2)/b) / 86400000 + x.append(p) + ft.append(x) + + + pyplot.plot(delta, ft[0], label='600 Buckets') + pyplot.plot(delta, ft[1], linestyle='dotted', label='1200 Buckets') + pyplot.plot(delta, ft[2], linestyle='dashed', label='1800 Buckets') + pyplot.plot(delta, ft[3], linestyle='dashdot', label='2400 Buckets') + pyplot.plot(delta, ft[4], label='3000 Buckets') + pyplot.ylim(bottom=0) + + pyplot.xlabel(r'$\Delta$') + pyplot.ylabel("Cores / Million Users") +# pyplot.title("Average Number of Bridge Users for 1 Month Old Bridges November 2021") + + + pyplot.legend(loc="upper right") + pyplot.tight_layout(pad=1) + pyplot.savefig("core-users.pdf") + +def set_plot_options(): + options = { + #'backend': 'PDF', + 'font.size': 18, + 'figure.figsize': (7,4), + 'figure.dpi': 100.0, + 'axes.grid' : True, + 'axes.xmargin' : 0, + 'axes.grid.axis' : 'y', + 'axes.axisbelow': True, + 'axes.titlesize' : 'medium', + 'axes.labelsize' : 'large', + 'axes.formatter.limits': (-6,6), + 'xtick.labelsize' : 18,#get_tick_font_size_10(), + 'ytick.labelsize' : 18, + 'lines.linewidth' : 2.0, + 'lines.markersize' : 10, + # turn on the following to embedd fonts; requires latex + 'ps.useafm' : True, + 'pdf.use14corefonts' : True, + 'text.usetex' : False, + } + + for option_key in options: + matplotlib.rcParams[option_key] = options[option_key] + + if 'figure.max_num_figures' in matplotlib.rcParams: + matplotlib.rcParams['figure.max_num_figures'] = 100 + if 'figure.max_open_warning' in matplotlib.rcParams: + matplotlib.rcParams['figure.max_open_warning'] = 100 + if 'legend.ncol' in matplotlib.rcParams: + matplotlib.rcParams['legend.ncol'] = 100 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/crates/lox-library/Parsing-results/make_tables.py b/crates/lox-library/Parsing-results/make_tables.py new file mode 100644 index 0000000..36e6d16 --- /dev/null +++ b/crates/lox-library/Parsing-results/make_tables.py @@ -0,0 +1,68 @@ +import csv +import sys +import pandas as pd +import numpy as np + + +def main(): + perf = open("performance_stats"+".csv", "w", newline='') + protocols=["Open Invitation", "Trust Promotion(0->1)", + "Trust Migration (0->1)", "Level Up (1->4)", "Issue Invitation", + "Redeem Invitation", "Check Blockage 5%", "Check Blockage 50%", "Check Blockage 100%", "Blockage Migration"] + files = ["trust_levels.csv", "trust_promo.csv", "trust_mig.csv", "level2.csv", + "invitations.csv", "redeem_invites.csv","check_blockage5.csv", + "check_blockage50.csv","check_blockage100.csv","check_blockage50.csv"] + csv_cols = ["RequestS", "RequestT","Rtstdev","ResponseS","ResponseT", + "ReTstdev", "ResponseHT", "RHTstdev"] + perf_columns = ["Protocol","Request Size", "Request Time", "sigma", + "Response Size","Response Time", "sigma", + "Response Handling Time", "sigma"] + worst_resp = 0 + perfwriter = csv.writer(perf, delimiter=',') + perfwriter.writerow(perf_columns) + + for i, protocol in enumerate(protocols): + columns = ["Percent","Bridges", "RequestS", "Rsstdev", "RequestT", + "Rtstdev", "ResponseS","Restdev","ResponseT", + "ReTstdev", "ResponseHT", "RHTstdev"] + df = pd.read_csv(files[i], usecols=columns) + perf_in = [] + + perf_in.append(protocol) + for item in csv_cols: + row = df[item].loc[df['Bridges']==900].values + if "stdev" in item: + rounded = np.round(row[0], decimals=1) + else: + rounded = np.round(row[0], decimals=3) + perf_in.append(rounded) + rounded = np.round(row[0], decimals=1) + if item == "RequestT": + req = np.round(rounded, decimals=1) + elif item == "ResponseT": + resp_sec = np.round(1000/rounded, decimals=1) + resp_core = resp_sec/(1/(60*60*24)) + if rounded > worst_resp: + worst_resp = rounded + + + perfwriter.writerow(perf_in) + + for i, protocol in enumerate(protocols): + columns = ["Percent","Bridges", "RequestS", "Rsstdev", "RequestT", + "Rtstdev", "ResponseS","Restdev","ResponseT", + "ReTstdev", "ResponseHT", "RHTstdev"] + df = pd.read_csv(files[i], usecols=columns) + row = df['ResponseT'].loc[df['Bridges']==900].values + rounded = np.round(row[0], decimals=3) + resp_sec = np.round(1000/rounded, decimals=3) + resp_core = int(resp_sec/(1/(60*60*24))) + if worst_resp > rounded: + secs = int(worst_resp/1000) + + perf.close() + print("\nDone Tables.\nTable data output to: performance_stats.csv,\n") + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/crates/lox-library/Parsing-results/parse_data.sh b/crates/lox-library/Parsing-results/parse_data.sh new file mode 100755 index 0000000..f8d30fb --- /dev/null +++ b/crates/lox-library/Parsing-results/parse_data.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# Parse results from Lox stat tests +echo 'Parse raw output to csv' + +python3 raw_to_csv.py + +echo 'Make plots for data' + +#python3 check_blockages.py +python3 pets_plots.py +#python3 trust_promo_plot.py +python3 make_tables.py +python3 make_steady.py diff --git a/crates/lox-library/Parsing-results/performance.py b/crates/lox-library/Parsing-results/performance.py new file mode 100644 index 0000000..0a3b58f --- /dev/null +++ b/crates/lox-library/Parsing-results/performance.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +import sys +import pandas as pd +import matplotlib +import matplotlib.pyplot as plt +from matplotlib.lines import Line2D + + +def main(): + set_plot_options() + fig, axs = plt.subplots(1) + columns = ["Percent","Bridges", "RequestT", "Rtstdev", "ResponseS", "ResponseT", + "ReTstdev", "ResponseHT", "RHTstdev"] + df = pd.read_csv("standard_check"+".csv", usecols=columns) + df.sort_values(["Percent"], axis=0,ascending=[False], inplace=True) + bridges = df.Bridges*2*3 + axs.set_xlabel('Blocked Bridges (%)') + axs.set_ylabel('Response Time (ms)') + axs.plot(df.Percent, df.ResponseT, color='#CC4F1B', + label='Response Time for Percentage of Bridges Blocked') + axs.set_ylim(bottom=0) + axs.fill_between(df.Percent, df.ResponseT-df.ReTstdev, + df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#CC4F1B', + facecolor='#FF9848') + fig. tight_layout(pad=1) + fig.savefig("StandardCheck.pdf") + +def set_plot_options(): + options = { + #'backend': 'PDF', + 'font.size': 18, + 'figure.figsize': (7,3.5), + 'figure.dpi': 100.0, + 'axes.grid' : True, + 'axes.xmargin' : 0, + 'axes.grid.axis' : 'y', + 'axes.axisbelow': True, + 'axes.titlesize' : 'medium', + 'axes.labelsize' : 'large', + 'axes.formatter.limits': (-6,6), + 'xtick.labelsize' : 18,#get_tick_font_size_10(), + 'ytick.labelsize' : 18, + 'lines.linewidth' : 2.0, + 'lines.markersize' : 10, + # turn on the following to embedd fonts; requires latex + 'ps.useafm' : True, + 'pdf.use14corefonts' : True, + 'text.usetex' : False, + } + + for option_key in options: + matplotlib.rcParams[option_key] = options[option_key] + + if 'figure.max_num_figures' in matplotlib.rcParams: + matplotlib.rcParams['figure.max_num_figures'] = 100 + if 'figure.max_open_warning' in matplotlib.rcParams: + matplotlib.rcParams['figure.max_open_warning'] = 100 + if 'legend.ncol' in matplotlib.rcParams: + matplotlib.rcParams['legend.ncol'] = 100 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/crates/lox-library/Parsing-results/pets_plots.py b/crates/lox-library/Parsing-results/pets_plots.py new file mode 100644 index 0000000..7683c99 --- /dev/null +++ b/crates/lox-library/Parsing-results/pets_plots.py @@ -0,0 +1,62 @@ +import sys +import pandas as pd +import matplotlib +import matplotlib.pyplot as plt +from matplotlib.lines import Line2D + + +def main(): + + plt.figure(figsize=(9, 5)) + columns = ["Percent","Bridges", "RequestT", "Rtstdev", "ResponseS", "ResponseT", + "ReTstdev", "ResponseHT", "RHTstdev"] + df = pd.read_csv("standard_check"+".csv", usecols=columns) + df.sort_values(["Percent"], axis=0,ascending=[False], inplace=True) + bridges = df.Bridges*2*3 + plt.xlabel('Blocked Bridges (%)', size=20) + plt.ylabel('Response Time (ms)', size=20) + plt.tick_params(axis='x', labelsize=15) + plt.tick_params(axis='y', labelsize=15) + plt.plot(df.Percent, df.ResponseT, color='#CC4F1B', + label='Response Time for Percentage of Bridges Blocked') + plt.fill_between(df.Percent, df.ResponseT-df.ReTstdev, + df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#CC4F1B', + facecolor='#FF9848') + plt.tight_layout(pad=1) + plt.savefig("StandardCheck.pdf") + plt.close('all') + +def set_plot_options(): + options = { + 'font.size': 12, + 'figure.figsize': (10,2), + 'figure.dpi': 100.0, + 'figure.subplot.left': 0.20, + 'figure.subplot.right': 0.97, + 'figure.subplot.bottom': 0.20, + 'figure.subplot.top': 0.90, + 'grid.color': '0.1', + 'grid.linestyle': ':', + #'grid.linewidth': 0.5, + 'axes.grid' : True, + #'axes.grid.axis' : 'y', + #'axes.axisbelow': True, + 'axes.titlesize' : 25, + 'axes.labelsize' : 25, + 'axes.formatter.limits': (-4,4), + 'xtick.labelsize' : 30,#get_tick_font_size_10(), + 'ytick.labelsize' : 30,#get_tick_font_size_10(), + 'lines.linewidth' : 2.0, + 'lines.markeredgewidth' : 0.5, + 'lines.markersize' : 15, + } + + for option_key in options: + matplotlib.rcParams[option_key] = options[option_key] + if 'figure.max_num_figures' in matplotlib.rcParams: + matplotlib.rcParams['figure.max_num_figures'] = 100 + if 'figure.max_open_warning' in matplotlib.rcParams: + matplotlib.rcParams['figure.max_open_warning'] = 100 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/crates/lox-library/Parsing-results/raw_to_csv.py b/crates/lox-library/Parsing-results/raw_to_csv.py new file mode 100644 index 0000000..090cd8e --- /dev/null +++ b/crates/lox-library/Parsing-results/raw_to_csv.py @@ -0,0 +1,176 @@ +from pathlib import Path + +standard_check_file = open("standard_check"+".csv", "w") +standard_check_file.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") + +for p in Path('.').glob('*.log'): + print(f"Parsing: {p.name.strip('.log')}\n") + with p.open() as log_file: + test_file = open(p.name.strip('.log')+".csv", "w") + test_file.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") + bridges = 0 + c=False + red = 0 + check = 0 + level = 0 + protocol = 0 + num = 0 + req_size = 0 + req_size_std = 0 + req_time = 0 + req_time_std = 0 + resp_size = 0 + resp_size_std = 0 + resp_time = 0 + resp_time_std = 0 + resp_handle_time = 0 + resp_handle_std = 0 + endline = 0 + + # Loop over the remaining lines in the file + for line in log_file: + if "***START" in line: + bridges = line.split()[1].split("*")[0] + if "CHECK-BLOCKAGE" in line: + protocol = 1 + num = line.split("-")[6].strip('-') + if int(bridges) == 900: + check =1 + if not c: + check_b = open("check_blockage"+str(num)+".csv", "w") + check_b.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") + c=True + elif "BLOCKAGE-MIGRATION" in line: + protocol = 2 + num = line.split("-")[6].strip('-') + elif "REDEEM" in line: + protocol = 3 + if not red: + redeem = open("redeem_invites.csv", "w") + redeem.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") + red = 1 + elif "ISSUE" in line: + protocol = 4 + elif "OPEN" in line: + protocol = 5 + elif "TRUST-PROMOTION" in line: + protocol = 6 + if not level: + trust_promo = open("trust_promo.csv", "w") + trust_promo.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") + elif "TRUST-MIGRATION" in line: + protocol = 7 + if not level: + mig_file = open("trust_mig.csv", "w") + mig_file.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") + elif "LEVEL-UP-2" in line: + protocol = 8 + if not level: + level_file = open("level2.csv", "w") + level_file.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") + elif "LEVEL-UP-3" in line: + protocol = 9 + if not level: + level_file_t = open("level3.csv", "w") + level_file_t.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") + elif "LEVEL-UP-4" in line: + protocol = 10 + if not level: + level_file_f = open("level4.csv", "w") + level_file_f.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") + level = 1 + elif protocol: + value = line.split(" = ") + if value[0].startswith("Average"): + if "request" in value[0]: + if "size" in value[0]: + raw_size = value[1].split(" ") + req_size = raw_size[0] + else: + if "µ" in value[1]: + micro_sec = value[1].split("µ") + raw_size = float(micro_sec[0])*0.001 + elif "m" not in value[1]: + sec = value[1][:-3] + raw_size = float(sec)*1000 + else: + raw_size = value[1][:-3] + req_time = raw_size + else: + if "size" in value[0]: + raw_size = value[1].split(" ") + resp_size = raw_size[0] + else: + if "µ" in value[1]: + micro_sec = value[1].split("µ") + raw_size = float(micro_sec[0])*0.001 + elif "m" not in value[1]: + sec = value[1][:-3] + raw_size = float(sec)*1000 + else: + raw_size = value[1][:-3] + if "handling" in value[0]: + resp_handle_time = raw_size + else: + resp_time = raw_size + elif value[0].startswith("Request"): + if "size" in value[0]: + raw_size = value[1].split(" ") + req_size_std = raw_size[0] + else: + if "µ" in value[1]: + micro_sec = value[1].split("µ") + to_sec = float(micro_sec[0])*0.001 + else: + to_sec = value[1][:-3] + req_time_std = to_sec + elif value[0].startswith("Response"): + if "size" in value[0]: + raw_size = value[1].split(" ") + resp_size_std = raw_size[0] + else: + if "µ" in value[1]: + micro_sec = value[1].split("µ") + to_sec = float(micro_sec[0])*0.001 + else: + to_sec = value[1][:-3] + if "handling" in value[0]: + resp_handle_time_std = to_sec + endline = 1 + else: + resp_time_std = to_sec + + if endline == 1: + if check == 1: + standard_check_file.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") + check = 0 + if protocol == 1: + check_b.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") + elif protocol == 3: + redeem.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") + elif protocol<6: + test_file.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") + else: + if protocol == 6: + trust_promo.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") + if protocol == 7: + mig_file.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") + if protocol == 8: + level_file.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") + elif protocol == 9: + level_file_t.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") + elif protocol == 10: + level_file_f.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") + endline = 0 + protocol = 0 + if level: + level_file.close() + level_file_t.close() + level_file_f.close() + trust_promo.close() + mig_file.close() + if red: + redeem.close() + test_file.close() +standard_check_file.close() +print("Done.") diff --git a/crates/lox-library/Parsing-results/trust_promo.py b/crates/lox-library/Parsing-results/trust_promo.py new file mode 100644 index 0000000..c8fb0ae --- /dev/null +++ b/crates/lox-library/Parsing-results/trust_promo.py @@ -0,0 +1,86 @@ +log_file = open("trust_levels.log", "r").readlines() +trust_promo_file = open("trust_promo"+".csv", "w") +trust_promo_file.write("Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") + + +bridges = 0 +promo = 0 +req_size = 0 +req_size_std = 0 +req_time = 0 +req_time_std = 0 +resp_size = 0 +resp_size_std = 0 +resp_time = 0 +resp_time_std = 0 +resp_handle_time = 0 +resp_handle_std = 0 +endline = 0 + +# Loop over the remaining lines in the file +for line in log_file: + if "***START" in line: + bridges = line.split()[1].split("*")[0] + elif "TRUST-PROMOTION" in line: + promo = 1 + elif promo: + value = line.split(" = ") + if value[0].startswith("Average"): + if "request" in value[0]: + if "size" in value[0]: + raw_size = value[1].split(" ") + req_size = raw_size[0] + else: + raw_size = value[1] + req_time = raw_size[:-3] + else: + if "size" in value[0]: + raw_size = value[1].split(" ") + resp_size = raw_size[0] + else: + raw_size = value[1] + if "handling" in value[0]: + resp_handle_time = raw_size[:-3] + elif (value[1][-3]) != "m": + sec = value[1][:-3] + resp_time = float(sec)*1000 + else: + resp_time = raw_size[:-3] + elif value[0].startswith("Request"): + if "size" in value[0]: + raw_size = value[1].split(" ") + req_size_std = raw_size[0] + else: + if "µ" in value[1]: + micro_sec = value[1].split("µ") + to_sec = float(micro_sec[0])*0.001 + else: + to_sec = value[1][:-3] + req_time_std = to_sec + + elif value[0].startswith("Response"): + if "size" in value[0]: + raw_size = value[1].split(" ") + resp_size_std = raw_size[0] + elif "bytes" in value[1]: + continue + else: + if "µ" in value[1]: + micro_sec = value[1].split("µ") + to_sec = float(micro_sec[0])*0.001 + else: + to_sec = value[1][:-3] + if "handling" in value[0]: + resp_handle_time_std = to_sec + endline = 1 + else: + resp_time_std = to_sec + + if endline == 1: + if promo == 1: + trust_promo_file.write(str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") + promo = 0 + endline = 0 + +trust_promo_file.close() +print("Done.") diff --git a/crates/lox-library/Parsing-results/trust_promo_plot.py b/crates/lox-library/Parsing-results/trust_promo_plot.py new file mode 100644 index 0000000..7c1eaea --- /dev/null +++ b/crates/lox-library/Parsing-results/trust_promo_plot.py @@ -0,0 +1,74 @@ +import sys +import pandas as pd +import matplotlib +import matplotlib.pyplot as plt +from matplotlib.lines import Line2D + + +def main(): + + fig, axs = plt.subplots(1, 3, figsize=(24, 7)) + columns = ["Bridges", "RequestT", "Rtstdev", "ResponseS", "ResponseT", + "ReTstdev", "ResponseHT", "RHTstdev"] + df = pd.read_csv("trust_promo"+".csv", usecols=columns) + bridges = df.Bridges*2*3 + fig.supxlabel('Total Size of Bridge Pool',size=30) + axs[0].set_ylabel('Response Time (ms)', size=25) + axs[0].tick_params(axis='x', labelsize=15) + axs[0].tick_params(axis='y', labelsize=15) + axs[0].plot(bridges, df.ResponseT, color='#29135F', + label='Response Time for Trust Promotion') + axs[0].fill_between(bridges, df.ResponseT-df.ReTstdev, + df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#29135F', + facecolor='#8967E2') + axs[1].set_ylabel('Response Size (bytes)', size=25) + axs[1].tick_params(axis='x', labelsize=15) + axs[1].tick_params(axis='y', labelsize=15) + axs[1].plot(bridges, df.ResponseS, color='#29135F', + label='Response Size for Trust Promotion') + axs[2].set_ylabel('Response Handling Time (ms)', size=25) + axs[2].tick_params(axis='x', labelsize=15) + axs[2].tick_params(axis='y', labelsize=15) + axs[2].plot(bridges, df.ResponseHT, color='#29135F', + label='Response Handling Time for Trust Promotion') + axs[2].fill_between(bridges, df.ResponseHT-df.RHTstdev, + df.ResponseHT+df.RHTstdev, alpha=0.5, edgecolor='#29135F', + facecolor='#8967E2') + fig. tight_layout(pad=1) + fig.savefig("TrustPromotion.pdf") + print("\nDone Trust Promotion Plot.\nOutput to: TrustPromotion.pdf") + +def set_plot_options(): + options = { + 'font.size': 12, + 'figure.figsize': (4,2), + 'figure.dpi': 100.0, + 'figure.subplot.left': 0.20, + 'figure.subplot.right': 0.97, + 'figure.subplot.bottom': 0.20, + 'figure.subplot.top': 0.90, + 'grid.color': '0.1', + 'grid.linestyle': ':', + #'grid.linewidth': 0.5, + 'axes.grid' : True, + #'axes.grid.axis' : 'y', + #'axes.axisbelow': True, + 'axes.titlesize' : 'large', + 'axes.labelsize' : 'x-large', + 'axes.formatter.limits': (-4,4), + 'xtick.labelsize' : 20,#get_tick_font_size_10(), + 'ytick.labelsize' : 20,#get_tick_font_size_10(), + 'lines.linewidth' : 2.0, + 'lines.markeredgewidth' : 0.5, + 'lines.markersize' : 10, + } + + for option_key in options: + matplotlib.rcParams[option_key] = options[option_key] + if 'figure.max_num_figures' in matplotlib.rcParams: + matplotlib.rcParams['figure.max_num_figures'] = 100 + if 'figure.max_open_warning' in matplotlib.rcParams: + matplotlib.rcParams['figure.max_open_warning'] = 100 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/crates/lox-library/README.md b/crates/lox-library/README.md index a4e08f3..f8572e0 100644 --- a/crates/lox-library/README.md +++ b/crates/lox-library/README.md @@ -10,7 +10,7 @@ Lox is written in rust and requires `cargo` to test. [Install Rust](https://www. ./run-lox.sh ``` -### To run the tests used for our experimental results run: +### To run the full tests used for our experimental results run: ``` cargo test --release -- --nocapture TESTNAME @@ -19,9 +19,9 @@ cargo test --release -- --nocapture TESTNAME Where `TESTNAME` is one of: ``` -stats_test_trust_levels +stats_test_trust_levels stats_test_invitations -stats_test_percent_blockage_migration_05 +stats_test_percent_blockage_migration_05 stats_test_percent_blockage_migration_010 stats_test_percent_blockage_migration_15 stats_test_percent_blockage_migration_20 @@ -29,11 +29,11 @@ stats_test_percent_blockage_migration_25 stats_test_percent_blockage_migration_30 stats_test_percent_blockage_migration_35 stats_test_percent_blockage_migration_40 -stats_test_percent_blockage_migration_45 +stats_test_percent_blockage_migration_45 stats_test_percent_blockage_migration_50 stats_test_percent_blockage_migration_55 stats_test_percent_blockage_migration_60 -stats_test_percent_blockage_migration_65 +stats_test_percent_blockage_migration_65 stats_test_percent_blockage_migration_70 stats_test_percent_blockage_migration_75 stats_test_percent_blockage_migration_80 @@ -43,7 +43,22 @@ stats_test_percent_blockage_migration_95 stats_test_percent_blockage_migration_100 ``` -Each test takes approximately 20-30 hours to run. +Each test takes approximately 20-30 hours to run. However, this can be improved +by passing the `fast` feature. Using this feature, our tests are run for 100 +users instead of 10000 users and will produce results comparable to our +reported results (with larger error margins). To run individual tests with this +flag run: + +``` + cargo test --release --features=fast -- --nocapture TESTNAME + ``` + + To run all tests in fast mode and output the results to the Parsing-results + directory, run: + +``` +./run_tests_fast +``` Note that: our implementation is coded such that the reachability certificate expires at 00:00 UTC. A workaround has been included in each test to pause if it is too close to this time so the request won't fail. 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). diff --git a/crates/lox-library/run_tests_fast.sh b/crates/lox-library/run_tests_fast.sh new file mode 100755 index 0000000..a5546b9 --- /dev/null +++ b/crates/lox-library/run_tests_fast.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +cargo test --release --features=fast -- --nocapture stats_test_trust_levels > trust_levels.log +cargo test --release --features=fast -- --nocapture stats_test_invitations > invitations.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_05 > check_blockage05.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_010 > check_blockage010.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_20 > check_blockage20.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_25 > check_blockage25.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_30 > check_blockage30.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_35 > check_blockage35.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_40 > check_blockage40.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_45 > check_blockage45.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_50 > check_blockage50.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_55 > check_blockage55.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_60 > check_blockage60.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_65 > check_blockage65.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_70 > check_blockage70.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_75 > check_blockage75.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_80 > check_blockage80.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_85 > check_blockage85.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_90 > check_blockage90.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_95 > check_blockage95.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_100 > check_blockage100.log +echo "Completed all tests, now parsing results" +mv *.log Parsing-results +cd Parsing-results +./parse_data.sh +echo "Parse results are in the Parsing-results folder." + diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 1766ed4..1c9f98e 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -11,6 +11,11 @@ use std::collections::HashSet; use std::thread; use std::time::{Duration, Instant}; +#[cfg(feature = "fast")] +const USERS: usize = 100; +#[cfg(not(feature = "fast"))] +const USERS: usize = 10000; + struct PerfStat { // Report performance metrics for each test req_len: usize, @@ -751,7 +756,7 @@ fn stats_test_trust_levels() { let mut open_req_time: Vec = Vec::new(); let mut open_resp_time: Vec = Vec::new(); let mut open_resp_handle_time: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -874,7 +879,7 @@ fn stats_test_invitations() { let mut red_req_time: Vec = Vec::new(); let mut red_resp_time: Vec = Vec::new(); let mut red_resp_handle_time: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { @@ -925,7 +930,7 @@ fn stats_test_percent_blockage_migration_05() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -958,7 +963,7 @@ fn stats_test_percent_blockage_migration_010() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -991,7 +996,7 @@ fn stats_test_percent_blockage_migration_15() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1024,7 +1029,7 @@ fn stats_test_percent_blockage_migration_20() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1057,7 +1062,7 @@ fn stats_test_percent_blockage_migration_25() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1090,7 +1095,7 @@ fn stats_test_percent_blockage_migration_30() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1123,7 +1128,7 @@ fn stats_test_percent_blockage_migration_35() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1156,7 +1161,7 @@ fn stats_test_percent_blockage_migration_40() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1189,7 +1194,7 @@ fn stats_test_percent_blockage_migration_45() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1222,7 +1227,7 @@ fn stats_test_percent_blockage_migration_50() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1255,7 +1260,7 @@ fn stats_test_percent_blockage_migration_55() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1288,7 +1293,7 @@ fn stats_test_percent_blockage_migration_60() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1321,7 +1326,7 @@ fn stats_test_percent_blockage_migration_65() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1354,7 +1359,7 @@ fn stats_test_percent_blockage_migration_70() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1387,7 +1392,7 @@ fn stats_test_percent_blockage_migration_75() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1420,7 +1425,7 @@ fn stats_test_percent_blockage_migration_80() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1453,7 +1458,7 @@ fn stats_test_percent_blockage_migration_85() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1486,7 +1491,7 @@ fn stats_test_percent_blockage_migration_90() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1519,7 +1524,7 @@ fn stats_test_percent_blockage_migration_95() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); @@ -1552,7 +1557,7 @@ fn stats_test_percent_blockage_migration_100() { for x in buckets { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); - for _ in 0..10000 { + for _ in 0..USERS { let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); From 993d01b712d150c043ee7fec5466cb41719a8f99 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Tue, 18 Oct 2022 00:51:17 -0400 Subject: [PATCH 084/115] Added results of cargo clippy --fix --- crates/lox-library/src/bridge_table.rs | 4 ++-- crates/lox-library/src/migration_table.rs | 4 ++-- .../src/proto/blockage_migration.rs | 8 ++++---- crates/lox-library/src/proto/check_blockage.rs | 4 ++-- crates/lox-library/src/proto/issue_invite.rs | 10 +++++----- crates/lox-library/src/proto/level_up.rs | 8 ++++---- crates/lox-library/src/proto/migration.rs | 8 ++++---- crates/lox-library/src/proto/open_invite.rs | 6 +++--- crates/lox-library/src/proto/redeem_invite.rs | 8 ++++---- .../lox-library/src/proto/trust_promotion.rs | 4 ++-- crates/lox-library/src/tests.rs | 18 +++++++++--------- 11 files changed, 41 insertions(+), 41 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index d7ef7fa..6f385a6 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -287,7 +287,7 @@ impl BridgeTable { let nonce = GenericArray::from_slice(&noncebytes); // Encrypt let cipher = Aes128Gcm::new(aeskey); - let ciphertext: Vec = cipher.encrypt(&nonce, plainbucket.as_ref()).unwrap(); + let ciphertext: Vec = cipher.encrypt(nonce, plainbucket.as_ref()).unwrap(); encbucket[0..12].copy_from_slice(&noncebytes); encbucket[12..].copy_from_slice(ciphertext.as_slice()); self.encbuckets.push(encbucket); @@ -307,7 +307,7 @@ impl BridgeTable { let aeskey = GenericArray::from_slice(key); // Decrypt let cipher = Aes128Gcm::new(aeskey); - let plaintext: Vec = cipher.decrypt(&nonce, encbucket[12..].as_ref())?; + let plaintext: Vec = cipher.decrypt(nonce, encbucket[12..].as_ref())?; // Convert the plaintext bytes to an array of BridgeLines Ok(BridgeLine::bucket_decode( plaintext.as_slice().try_into().unwrap(), diff --git a/crates/lox-library/src/migration_table.rs b/crates/lox-library/src/migration_table.rs index 4a596f1..86d5aa8 100644 --- a/crates/lox-library/src/migration_table.rs +++ b/crates/lox-library/src/migration_table.rs @@ -127,7 +127,7 @@ pub fn encrypt_cred( let aeskey = GenericArray::from_slice(&fullhash[16..]); // Encrypt let cipher = Aes128Gcm::new(aeskey); - let ciphertext: Vec = cipher.encrypt(&nonce, credbytes.as_ref()).unwrap(); + let ciphertext: Vec = cipher.encrypt(nonce, credbytes.as_ref()).unwrap(); let mut enccredbytes: [u8; ENC_MIGRATION_BYTES] = [0; ENC_MIGRATION_BYTES]; enccredbytes[..12].copy_from_slice(&noncebytes); enccredbytes[12..].copy_from_slice(ciphertext.as_slice()); @@ -239,7 +239,7 @@ pub fn decrypt_cred( // Decrypt let nonce = GenericArray::from_slice(&ciphertext[..12]); let cipher = Aes128Gcm::new(aeskey); - let plaintext: Vec = match cipher.decrypt(&nonce, ciphertext[12..].as_ref()) { + let plaintext: Vec = match cipher.decrypt(nonce, ciphertext[12..].as_ref()) { Ok(v) => v, Err(_) => return None, }; diff --git a/crates/lox-library/src/proto/blockage_migration.rs b/crates/lox-library/src/proto/blockage_migration.rs index dc8c5b6..4705535 100644 --- a/crates/lox-library/src/proto/blockage_migration.rs +++ b/crates/lox-library/src/proto/blockage_migration.rs @@ -299,8 +299,8 @@ pub fn request( let piUser = requestproof::prove_compact( &mut transcript, requestproof::ProveAssignments { - A: &A, - B: &B, + A, + B, P_lox: &P_lox, CBucket: &CBucket, CSince: &CSince, @@ -531,8 +531,8 @@ impl BridgeAuth { let piBlindIssue = blindissue::prove_compact( &mut transcript, blindissue::ProveAssignments { - A: &A, - B: &B, + A, + B, P: &P, EncQ0: &EncQ.0, EncQ1: &EncQ.1, diff --git a/crates/lox-library/src/proto/check_blockage.rs b/crates/lox-library/src/proto/check_blockage.rs index 9cba4fc..34b3823 100644 --- a/crates/lox-library/src/proto/check_blockage.rs +++ b/crates/lox-library/src/proto/check_blockage.rs @@ -186,8 +186,8 @@ pub fn request( let piUser = requestproof::prove_compact( &mut transcript, requestproof::ProveAssignments { - A: &A, - B: &B, + A, + B, P: &P, CBucket: &CBucket, CSince: &CSince, diff --git a/crates/lox-library/src/proto/issue_invite.rs b/crates/lox-library/src/proto/issue_invite.rs index f2ed162..610de25 100644 --- a/crates/lox-library/src/proto/issue_invite.rs +++ b/crates/lox-library/src/proto/issue_invite.rs @@ -408,8 +408,8 @@ pub fn request( let piUser = requestproof::prove_compact( &mut transcript, requestproof::ProveAssignments { - A: &A, - B: &B, + A, + B, P: &P, CBucket: &CBucket, CLevel: &CLevel, @@ -464,7 +464,7 @@ pub fn request( id_client: &id_client, inv_id_client: &inv_id_client, einv_id_client: &einv_id_client, - invremain_inverse: &invremain_inverse, + invremain_inverse, zinvremain_inverse: &zinvremain_inverse, }, ) @@ -698,8 +698,8 @@ impl BridgeAuth { let piBlindIssue = blindissue::prove_compact( &mut transcript, blindissue::ProveAssignments { - A: &A, - B: &B, + A, + B, P: &P, EncQ0: &EncQ.0, EncQ1: &EncQ.1, diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs index 7978e68..5f9bc30 100644 --- a/crates/lox-library/src/proto/level_up.rs +++ b/crates/lox-library/src/proto/level_up.rs @@ -524,8 +524,8 @@ pub fn request( let piUser = requestproof::prove_compact( &mut transcript, requestproof::ProveAssignments { - A: &A, - B: &B, + A, + B, P: &P, CBucket: &CBucket, CSince: &CSince, @@ -874,8 +874,8 @@ impl BridgeAuth { let piBlindIssue = blindissue::prove_compact( &mut transcript, blindissue::ProveAssignments { - A: &A, - B: &B, + A, + B, P: &P, EncQ0: &EncQ.0, EncQ1: &EncQ.1, diff --git a/crates/lox-library/src/proto/migration.rs b/crates/lox-library/src/proto/migration.rs index 383dfa2..585f5b5 100644 --- a/crates/lox-library/src/proto/migration.rs +++ b/crates/lox-library/src/proto/migration.rs @@ -246,8 +246,8 @@ pub fn request( let piUser = requestproof::prove_compact( &mut transcript, requestproof::ProveAssignments { - A: &A, - B: &B, + A, + B, P_lox: &P_lox, CBucket: &CBucket, CSince: &CSince, @@ -428,8 +428,8 @@ impl BridgeAuth { let piBlindIssue = blindissue::prove_compact( &mut transcript, blindissue::ProveAssignments { - A: &A, - B: &B, + A, + B, P: &P, EncQ0: &EncQ.0, EncQ1: &EncQ.1, diff --git a/crates/lox-library/src/proto/open_invite.rs b/crates/lox-library/src/proto/open_invite.rs index 306489a..818b32b 100644 --- a/crates/lox-library/src/proto/open_invite.rs +++ b/crates/lox-library/src/proto/open_invite.rs @@ -121,7 +121,7 @@ pub fn request(invite: &[u8; OPENINV_LENGTH]) -> (Request, State) { let piUserBlinding = userblinding::prove_compact( &mut transcript, userblinding::ProveAssignments { - B: &B, + B, D: &D, EncIdClient0: &EncIdClient.0, EncIdClient1: &EncIdClient.1, @@ -228,8 +228,8 @@ impl BridgeAuth { let piBlindIssue = blindissue::prove_compact( &mut transcript, blindissue::ProveAssignments { - A: &A, - B: &B, + A, + B, P: &P, EncQ0: &EncQ.0, EncQ1: &EncQ.1, diff --git a/crates/lox-library/src/proto/redeem_invite.rs b/crates/lox-library/src/proto/redeem_invite.rs index 59ce73b..6692a38 100644 --- a/crates/lox-library/src/proto/redeem_invite.rs +++ b/crates/lox-library/src/proto/redeem_invite.rs @@ -290,8 +290,8 @@ pub fn request( let piUser = requestproof::prove_compact( &mut transcript, requestproof::ProveAssignments { - A: &A, - B: &B, + A, + B, P: &P, CDate: &CDate, CBucket: &CBucket, @@ -498,8 +498,8 @@ impl BridgeAuth { let piBlindIssue = blindissue::prove_compact( &mut transcript, blindissue::ProveAssignments { - A: &A, - B: &B, + A, + B, P: &P, EncQ0: &EncQ.0, EncQ1: &EncQ.1, diff --git a/crates/lox-library/src/proto/trust_promotion.rs b/crates/lox-library/src/proto/trust_promotion.rs index fed5a25..9642c8f 100644 --- a/crates/lox-library/src/proto/trust_promotion.rs +++ b/crates/lox-library/src/proto/trust_promotion.rs @@ -301,8 +301,8 @@ pub fn request( let piUser = requestproof::prove_compact( &mut transcript, requestproof::ProveAssignments { - A: &A, - B: &B, + A, + B, P: &P, CBucket: &CBucket, CSince: &CSince, diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 1c9f98e..e2b65ea 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -108,7 +108,7 @@ impl TestHarness { fn trust_promotion(&mut self, cred: &cred::Lox) -> (PerfStat, cred::Migration) { let req_start = Instant::now(); let (promreq, promstate) = - trust_promotion::request(&cred, &self.ba.lox_pub, self.ba.today()).unwrap(); + trust_promotion::request(cred, &self.ba.lox_pub, self.ba.today()).unwrap(); let encoded: Vec = bincode::serialize(&promreq).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); @@ -187,7 +187,7 @@ impl TestHarness { // level let req_start = Instant::now(); let (req, state) = level_up::request( - &cred, + cred, &reachcred, &self.ba.lox_pub, &self.ba.reachability_pub, @@ -233,7 +233,7 @@ impl TestHarness { let req_start = Instant::now(); let (req, state) = issue_invite::request( - &cred, + cred, &reachcred, &self.ba.lox_pub, &self.ba.reachability_pub, @@ -277,7 +277,7 @@ impl TestHarness { fn redeem_invite(&mut self, inv: &cred::Invitation) -> (PerfStat, cred::Lox) { let req_start = Instant::now(); let (req, state) = - redeem_invite::request(&inv, &self.ba.invitation_pub, self.ba.today()).unwrap(); + redeem_invite::request(inv, &self.ba.invitation_pub, self.ba.today()).unwrap(); let encoded: Vec = bincode::serialize(&req).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); @@ -308,7 +308,7 @@ impl TestHarness { fn check_blockage(&mut self, cred: &cred::Lox) -> (PerfStat, cred::Migration) { let req_start = Instant::now(); - let (req, state) = check_blockage::request(&cred, &self.ba.lox_pub).unwrap(); + let (req, state) = check_blockage::request(cred, &self.ba.lox_pub).unwrap(); let encoded: Vec = bincode::serialize(&req).unwrap(); let req_t = req_start.elapsed(); let req_len = encoded.len(); @@ -344,7 +344,7 @@ impl TestHarness { ) -> (PerfStat, cred::Lox) { let req_start = Instant::now(); let (req, state) = - blockage_migration::request(&cred, &mig, &self.ba.lox_pub, &self.ba.migration_pub) + blockage_migration::request(cred, mig, &self.ba.lox_pub, &self.ba.migration_pub) .unwrap(); let encoded: Vec = bincode::serialize(&req).unwrap(); let req_t = req_start.elapsed(); @@ -1592,11 +1592,11 @@ fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec = HashSet::new(); let mut rng = rand::thread_rng(); - while block_index.len() <= to_block - 1 { + while block_index.len() < to_block { let rand_num = rng.gen_range(0, blockable_range); if !th.bdb.openinv_buckets.contains(&(rand_num as u32)) { block_index.insert(rand_num); @@ -1631,7 +1631,7 @@ fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec Date: Fri, 14 Oct 2022 14:20:32 -0400 Subject: [PATCH 085/115] Add MIT licence --- crates/lox-library/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 crates/lox-library/LICENSE diff --git a/crates/lox-library/LICENSE b/crates/lox-library/LICENSE new file mode 100644 index 0000000..52402c0 --- /dev/null +++ b/crates/lox-library/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Ian Goldberg and Lindsey Tulloch + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 9f0fb0bbe16e0b8484c82144d4cd2414865e9394 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Tue, 18 Oct 2022 00:52:10 -0400 Subject: [PATCH 086/115] Docker works as expected, README updated --- crates/lox-library/Dockerfile | 6 ++-- crates/lox-library/README.md | 61 ++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/crates/lox-library/Dockerfile b/crates/lox-library/Dockerfile index 35f7a44..8f5796d 100644 --- a/crates/lox-library/Dockerfile +++ b/crates/lox-library/Dockerfile @@ -6,9 +6,9 @@ ADD tests/ ./tests/ ADD run_tests_fast.sh . ADD Parsing-results ./Parsing-results ADD README.md README.md -RUN apt-get update -y -RUN apt-get install -y python3 python3-pip -RUN pip3 install pandas +RUN apt update -y +RUN apt install -y python3 python3-pip +RUN pip3 install pandas RUN pip3 install numpy RUN pip3 install matplotlib RUN cargo build --release diff --git a/crates/lox-library/README.md b/crates/lox-library/README.md index f8572e0..ba48997 100644 --- a/crates/lox-library/README.md +++ b/crates/lox-library/README.md @@ -1,7 +1,7 @@ # 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) +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. ### To use the docker environment to build the package: @@ -10,56 +10,57 @@ Lox is written in rust and requires `cargo` to test. [Install Rust](https://www. ./run-lox.sh ``` -### To run the full tests used for our experimental results run: +### To run each of the tests used for our experimental results run: ``` -cargo test --release -- --nocapture TESTNAME +cargo test --release -- --nocapture TESTNAME > LOGFILE ``` -Where `TESTNAME` is one of: +Where `TESTNAME > LOGFILE` is one of: ``` -stats_test_trust_levels -stats_test_invitations -stats_test_percent_blockage_migration_05 -stats_test_percent_blockage_migration_010 -stats_test_percent_blockage_migration_15 -stats_test_percent_blockage_migration_20 -stats_test_percent_blockage_migration_25 -stats_test_percent_blockage_migration_30 -stats_test_percent_blockage_migration_35 -stats_test_percent_blockage_migration_40 -stats_test_percent_blockage_migration_45 -stats_test_percent_blockage_migration_50 -stats_test_percent_blockage_migration_55 -stats_test_percent_blockage_migration_60 -stats_test_percent_blockage_migration_65 -stats_test_percent_blockage_migration_70 -stats_test_percent_blockage_migration_75 -stats_test_percent_blockage_migration_80 -stats_test_percent_blockage_migration_85 -stats_test_percent_blockage_migration_90 -stats_test_percent_blockage_migration_95 -stats_test_percent_blockage_migration_100 +stats_test_trust_levels > trust_levels.log +stats_test_invitations > invitations.log +stats_test_percent_blockage_migration_05 > check_blockage05.log +stats_test_percent_blockage_migration_010 > check_blockage010.log +stats_test_percent_blockage_migration_20 > check_blockage20.log +stats_test_percent_blockage_migration_25 > check_blockage25.log +stats_test_percent_blockage_migration_35 > check_blockage35.log +stats_test_percent_blockage_migration_40 > check_blockage40.log +stats_test_percent_blockage_migration_45 > check_blockage45.log +stats_test_percent_blockage_migration_50 > check_blockage50.log +stats_test_percent_blockage_migration_55 > check_blockage55.log +stats_test_percent_blockage_migration_60 > check_blockage60.log +stats_test_percent_blockage_migration_65 > check_blockage65.log +stats_test_percent_blockage_migration_70 > check_blockage70.log +stats_test_percent_blockage_migration_75 > check_blockage75.log +stats_test_percent_blockage_migration_80 > check_blockage80.log +stats_test_percent_blockage_migration_85 > check_blockage85.log +stats_test_percent_blockage_migration_90 > check_blockage90.log +stats_test_percent_blockage_migration_95 > check_blockage95.log +stats_test_percent_blockage_migration_100 > check_blockage100.log ``` -Each test takes approximately 20-30 hours to run. However, this can be improved +Each test outputs results to the specified log file and takes approximately 20-30 hours to run. However, this can be improved by passing the `fast` feature. Using this feature, our tests are run for 100 users instead of 10000 users and will produce results comparable to our reported results (with larger error margins). To run individual tests with this flag run: ``` - cargo test --release --features=fast -- --nocapture TESTNAME + cargo test --release --features=fast -- --nocapture TESTNAME > LOGFILE ``` - To run all tests in fast mode and output the results to the Parsing-results - directory, run: +We have also included the scripts we used to parse the output from each of the Lox tests in the `Parsing-results` directory. For convenience, copy all of the output log files to the `Parsing-results` directory and run `./parse_data.sh`. This is a python script that uses Python 3.8+ and depends on `numpy`, `matplotlib`, and `pandas` which can be installed with `pip3`. + +To run all tests in fast mode, output the results to the `Parsing-results` directory, and generate the table (`performance_stats.csv`, our Table 4) and graphs (`StandardCheck.pdf` and `core-users.pdf`, our Figures 1 and 2) used in our paper, run: ``` ./run_tests_fast ``` +This should take approximately 9 hours to complete. + Note that: our implementation is coded such that the reachability certificate expires at 00:00 UTC. A workaround has been included in each test to pause if it is too close to this time so the request won't fail. 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). From 2818ce67f4c26081ddfcfe23f49934e4ea7370cf Mon Sep 17 00:00:00 2001 From: onyinyang Date: Thu, 20 Oct 2022 00:43:31 -0400 Subject: [PATCH 087/115] Added some fixes and requested touchups from artifact review --- crates/lox-library/Dockerfile | 4 +- .../Parsing-results/make_tables.py | 2 +- .../lox-library/Parsing-results/pets_plots.py | 2 +- .../Parsing-results/requirements.txt | 15 ++++++++ crates/lox-library/README.md | 38 +++++++++---------- crates/lox-library/run_tests_fast.sh | 38 +++++++++---------- crates/lox-library/src/tests.rs | 11 +++--- 7 files changed, 61 insertions(+), 49 deletions(-) create mode 100644 crates/lox-library/Parsing-results/requirements.txt diff --git a/crates/lox-library/Dockerfile b/crates/lox-library/Dockerfile index 8f5796d..954c37f 100644 --- a/crates/lox-library/Dockerfile +++ b/crates/lox-library/Dockerfile @@ -8,8 +8,6 @@ ADD Parsing-results ./Parsing-results ADD README.md README.md RUN apt update -y RUN apt install -y python3 python3-pip -RUN pip3 install pandas -RUN pip3 install numpy -RUN pip3 install matplotlib +RUN pip3 install -r Parsing-results/requirements.txt RUN cargo build --release ENV SHELL=/bin/bash diff --git a/crates/lox-library/Parsing-results/make_tables.py b/crates/lox-library/Parsing-results/make_tables.py index 36e6d16..61a0eea 100644 --- a/crates/lox-library/Parsing-results/make_tables.py +++ b/crates/lox-library/Parsing-results/make_tables.py @@ -11,7 +11,7 @@ def main(): "Redeem Invitation", "Check Blockage 5%", "Check Blockage 50%", "Check Blockage 100%", "Blockage Migration"] files = ["trust_levels.csv", "trust_promo.csv", "trust_mig.csv", "level2.csv", "invitations.csv", "redeem_invites.csv","check_blockage5.csv", - "check_blockage50.csv","check_blockage100.csv","check_blockage50.csv"] + "check_blockage50.csv","check_blockage100.csv","blockage_migration50.csv"] csv_cols = ["RequestS", "RequestT","Rtstdev","ResponseS","ResponseT", "ReTstdev", "ResponseHT", "RHTstdev"] perf_columns = ["Protocol","Request Size", "Request Time", "sigma", diff --git a/crates/lox-library/Parsing-results/pets_plots.py b/crates/lox-library/Parsing-results/pets_plots.py index 7683c99..df8557f 100644 --- a/crates/lox-library/Parsing-results/pets_plots.py +++ b/crates/lox-library/Parsing-results/pets_plots.py @@ -23,7 +23,7 @@ def main(): df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#CC4F1B', facecolor='#FF9848') plt.tight_layout(pad=1) - plt.savefig("StandardCheck.pdf") + plt.savefig("Blockage-response-time.pdf") plt.close('all') def set_plot_options(): diff --git a/crates/lox-library/Parsing-results/requirements.txt b/crates/lox-library/Parsing-results/requirements.txt new file mode 100644 index 0000000..77e0143 --- /dev/null +++ b/crates/lox-library/Parsing-results/requirements.txt @@ -0,0 +1,15 @@ +contourpy==1.0.5 +cycler==0.11.0 +fonttools==4.37.4 +kiwisolver==1.4.4 +matplotlib==3.6.1 +mercurial==5.6.1 +numpy==1.23.4 +packaging==21.3 +pandas==1.5.0 +Pillow==9.2.0 +pyparsing==3.0.9 +python-dateutil==2.8.2 +pytz==2022.4 +six==1.16.0 + diff --git a/crates/lox-library/README.md b/crates/lox-library/README.md index ba48997..c3cfd4a 100644 --- a/crates/lox-library/README.md +++ b/crates/lox-library/README.md @@ -21,24 +21,24 @@ Where `TESTNAME > LOGFILE` is one of: ``` stats_test_trust_levels > trust_levels.log stats_test_invitations > invitations.log -stats_test_percent_blockage_migration_05 > check_blockage05.log -stats_test_percent_blockage_migration_010 > check_blockage010.log -stats_test_percent_blockage_migration_20 > check_blockage20.log -stats_test_percent_blockage_migration_25 > check_blockage25.log -stats_test_percent_blockage_migration_35 > check_blockage35.log -stats_test_percent_blockage_migration_40 > check_blockage40.log -stats_test_percent_blockage_migration_45 > check_blockage45.log -stats_test_percent_blockage_migration_50 > check_blockage50.log -stats_test_percent_blockage_migration_55 > check_blockage55.log -stats_test_percent_blockage_migration_60 > check_blockage60.log -stats_test_percent_blockage_migration_65 > check_blockage65.log -stats_test_percent_blockage_migration_70 > check_blockage70.log -stats_test_percent_blockage_migration_75 > check_blockage75.log -stats_test_percent_blockage_migration_80 > check_blockage80.log -stats_test_percent_blockage_migration_85 > check_blockage85.log -stats_test_percent_blockage_migration_90 > check_blockage90.log -stats_test_percent_blockage_migration_95 > check_blockage95.log -stats_test_percent_blockage_migration_100 > check_blockage100.log +stats_test_percent_blockage_migration_05 > blockage_migration05.log +stats_test_percent_blockage_migration_010 > blockage_migration010.log +stats_test_percent_blockage_migration_20 > blockage_migration20.log +stats_test_percent_blockage_migration_25 > blockage_migration25.log +stats_test_percent_blockage_migration_35 > blockage_migration35.log +stats_test_percent_blockage_migration_40 > blockage_migration40.log +stats_test_percent_blockage_migration_45 > blockage_migration45.log +stats_test_percent_blockage_migration_50 > blockage_migration50.log +stats_test_percent_blockage_migration_55 > blockage_migration55.log +stats_test_percent_blockage_migration_60 > blockage_migration60.log +stats_test_percent_blockage_migration_65 > blockage_migration65.log +stats_test_percent_blockage_migration_70 > blockage_migration70.log +stats_test_percent_blockage_migration_75 > blockage_migration75.log +stats_test_percent_blockage_migration_80 > blockage_migration80.log +stats_test_percent_blockage_migration_85 > blockage_migration85.log +stats_test_percent_blockage_migration_90 > blockage_migration90.log +stats_test_percent_blockage_migration_95 > blockage_migration95.log +stats_test_percent_blockage_migration_100 > blockage_migration100.log ``` Each test outputs results to the specified log file and takes approximately 20-30 hours to run. However, this can be improved @@ -53,7 +53,7 @@ flag run: We have also included the scripts we used to parse the output from each of the Lox tests in the `Parsing-results` directory. For convenience, copy all of the output log files to the `Parsing-results` directory and run `./parse_data.sh`. This is a python script that uses Python 3.8+ and depends on `numpy`, `matplotlib`, and `pandas` which can be installed with `pip3`. -To run all tests in fast mode, output the results to the `Parsing-results` directory, and generate the table (`performance_stats.csv`, our Table 4) and graphs (`StandardCheck.pdf` and `core-users.pdf`, our Figures 1 and 2) used in our paper, run: +To run all tests in fast mode, output the results to the `Parsing-results` directory, and generate the table (`performance_stats.csv`, our Table 4) and graphs (`Blockage-response-time.pdf` and `core-users.pdf`, our Figures 1 and 2) used in our paper, run: ``` ./run_tests_fast diff --git a/crates/lox-library/run_tests_fast.sh b/crates/lox-library/run_tests_fast.sh index a5546b9..4b43063 100755 --- a/crates/lox-library/run_tests_fast.sh +++ b/crates/lox-library/run_tests_fast.sh @@ -2,25 +2,25 @@ cargo test --release --features=fast -- --nocapture stats_test_trust_levels > trust_levels.log cargo test --release --features=fast -- --nocapture stats_test_invitations > invitations.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_05 > check_blockage05.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_010 > check_blockage010.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_20 > check_blockage20.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_25 > check_blockage25.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_30 > check_blockage30.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_35 > check_blockage35.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_40 > check_blockage40.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_45 > check_blockage45.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_50 > check_blockage50.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_55 > check_blockage55.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_60 > check_blockage60.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_65 > check_blockage65.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_70 > check_blockage70.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_75 > check_blockage75.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_80 > check_blockage80.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_85 > check_blockage85.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_90 > check_blockage90.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_95 > check_blockage95.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_100 > check_blockage100.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_05 > blockage_migration05.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_010 > blockage_migration010.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_20 > blockage_migration20.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_25 > blockage_migration25.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_30 > blockage_migration30.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_35 > blockage_migration35.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_40 > blockage_migration40.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_45 > blockage_migration45.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_50 > blockage_migration50.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_55 > blockage_migration55.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_60 > blockage_migration60.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_65 > blockage_migration65.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_70 > blockage_migration70.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_75 > blockage_migration75.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_80 > blockage_migration80.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_85 > blockage_migration85.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_90 > blockage_migration90.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_95 > blockage_migration95.log +cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_100 > blockage_migration100.log echo "Completed all tests, now parsing results" mv *.log Parsing-results cd Parsing-results diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index e2b65ea..58f4911 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -1686,16 +1686,15 @@ fn print_stats_test_results( resp_handle_time: Vec, ) { let mean_req_size = mean(&req_size); - let req_std_dev = standard_deviation(&req_size, Some(mean_req_size)); + let req_std_dev = if &req_size.len() > &1 {standard_deviation(&req_size, Some(mean_req_size))} else {0.0}; let mean_req_time = mean(&req_time); - let req_time_std_dev = standard_deviation(&req_time, Some(mean_req_time)); + let req_time_std_dev = if &req_time.len() > &1 {standard_deviation(&req_time, Some(mean_req_time))} else {0.0}; let mean_resp_size = mean(&resp_size); - let resp_std_dev = standard_deviation(&resp_size, Some(mean_resp_size)); + let resp_std_dev = if &resp_size.len() > &1 {standard_deviation(&resp_size, Some(mean_resp_size))} else {0.0}; let mean_resp_time = mean(&resp_time); - let resp_time_std_dev = standard_deviation(&resp_time, Some(mean_resp_time)); + let resp_time_std_dev = if &resp_time.len() > &1 {standard_deviation(&resp_time, Some(mean_resp_time))} else {0.0}; let mean_resp_handle_time = mean(&resp_handle_time); - let resp_handle_time_std_dev = - standard_deviation(&resp_handle_time, Some(mean_resp_handle_time)); + let resp_handle_time_std_dev = if &resp_handle_time.len() > &1 {standard_deviation(&resp_handle_time, Some(mean_resp_handle_time))} else {0.0}; println!("Average request size = {} bytes", mean_req_size); println!("Request size standard deviation = {} bytes", req_std_dev); From efc175b45b8dda17f93950bd673106b8a360e4e3 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Thu, 20 Oct 2022 11:25:48 -0400 Subject: [PATCH 088/115] Don't crash if we get 0 data points for small experiments --- crates/lox-library/src/tests.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 58f4911..931a103 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -1685,16 +1685,16 @@ fn print_stats_test_results( resp_time: Vec, resp_handle_time: Vec, ) { - let mean_req_size = mean(&req_size); - let req_std_dev = if &req_size.len() > &1 {standard_deviation(&req_size, Some(mean_req_size))} else {0.0}; - let mean_req_time = mean(&req_time); - let req_time_std_dev = if &req_time.len() > &1 {standard_deviation(&req_time, Some(mean_req_time))} else {0.0}; - let mean_resp_size = mean(&resp_size); - let resp_std_dev = if &resp_size.len() > &1 {standard_deviation(&resp_size, Some(mean_resp_size))} else {0.0}; - let mean_resp_time = mean(&resp_time); - let resp_time_std_dev = if &resp_time.len() > &1 {standard_deviation(&resp_time, Some(mean_resp_time))} else {0.0}; - let mean_resp_handle_time = mean(&resp_handle_time); - let resp_handle_time_std_dev = if &resp_handle_time.len() > &1 {standard_deviation(&resp_handle_time, Some(mean_resp_handle_time))} else {0.0}; + let mean_req_size = if req_size.len() > 0 {mean(&req_size)} else {0.0}; + let req_std_dev = if req_size.len() > 1 {standard_deviation(&req_size, Some(mean_req_size))} else {0.0}; + let mean_req_time = if req_time.len() > 0 {mean(&req_time)} else {0.0}; + let req_time_std_dev = if req_time.len() > 1 {standard_deviation(&req_time, Some(mean_req_time))} else {0.0}; + let mean_resp_size = if resp_size.len() > 0 {mean(&resp_size)} else {0.0}; + let resp_std_dev = if resp_size.len() > 1 {standard_deviation(&resp_size, Some(mean_resp_size))} else {0.0}; + let mean_resp_time = if resp_time.len() > 0 {mean(&resp_time)} else {0.0}; + let resp_time_std_dev = if resp_time.len() > 1 {standard_deviation(&resp_time, Some(mean_resp_time))} else {0.0}; + let mean_resp_handle_time = if resp_handle_time.len() > 0 {mean(&resp_handle_time)} else {0.0}; + let resp_handle_time_std_dev = if resp_handle_time.len() > 1 {standard_deviation(&resp_handle_time, Some(mean_resp_handle_time))} else {0.0}; println!("Average request size = {} bytes", mean_req_size); println!("Request size standard deviation = {} bytes", req_std_dev); From 4eca0327451408b27ee0c22bc73302a18e1f903e Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Thu, 20 Oct 2022 11:34:39 -0400 Subject: [PATCH 089/115] cargo fmt --- crates/lox-library/src/tests.rs | 150 ++++++++++++++++++++------------ 1 file changed, 95 insertions(+), 55 deletions(-) diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 931a103..d69bc22 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -4,7 +4,7 @@ BridgeLine::random() or private fields */ use super::bridge_table::BridgeLine; use super::proto::*; use super::*; -use chrono::{Utc, DateTime, NaiveTime, Timelike}; +use chrono::{DateTime, NaiveTime, Timelike, Utc}; use rand::Rng; use statistical::{mean, standard_deviation}; use std::collections::HashSet; @@ -757,10 +757,10 @@ fn stats_test_trust_levels() { let mut open_resp_time: Vec = Vec::new(); let mut open_resp_handle_time: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let (open_perf_stat, cred) = th.open_invite(); @@ -880,11 +880,11 @@ fn stats_test_invitations() { let mut red_resp_time: Vec = Vec::new(); let mut red_resp_handle_time: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -931,10 +931,10 @@ fn stats_test_percent_blockage_migration_05() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -964,10 +964,10 @@ fn stats_test_percent_blockage_migration_010() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -997,10 +997,10 @@ fn stats_test_percent_blockage_migration_15() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1030,10 +1030,10 @@ fn stats_test_percent_blockage_migration_20() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1063,10 +1063,10 @@ fn stats_test_percent_blockage_migration_25() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1096,10 +1096,10 @@ fn stats_test_percent_blockage_migration_30() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1129,10 +1129,10 @@ fn stats_test_percent_blockage_migration_35() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1162,10 +1162,10 @@ fn stats_test_percent_blockage_migration_40() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1195,10 +1195,10 @@ fn stats_test_percent_blockage_migration_45() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1228,10 +1228,10 @@ fn stats_test_percent_blockage_migration_50() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1261,10 +1261,10 @@ fn stats_test_percent_blockage_migration_55() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1294,10 +1294,10 @@ fn stats_test_percent_blockage_migration_60() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1327,10 +1327,10 @@ fn stats_test_percent_blockage_migration_65() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1360,10 +1360,10 @@ fn stats_test_percent_blockage_migration_70() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1393,10 +1393,10 @@ fn stats_test_percent_blockage_migration_75() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1426,10 +1426,10 @@ fn stats_test_percent_blockage_migration_80() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1459,10 +1459,10 @@ fn stats_test_percent_blockage_migration_85() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1492,10 +1492,10 @@ fn stats_test_percent_blockage_migration_90() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1525,10 +1525,10 @@ fn stats_test_percent_blockage_migration_95() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1558,10 +1558,10 @@ fn stats_test_percent_blockage_migration_100() { let mut th = TestHarness::new_buckets(x, x); let mut credentials: Vec = Vec::new(); for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); + let h: NaiveTime = DateTime::time(&Utc::now()); if h.hour() == 23 && h.minute() == 59 { println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60,0)); + thread::sleep(Duration::new(60, 0)); println!("Ready to work again"); } let cred = th.open_invite().1 .0; @@ -1685,16 +1685,56 @@ fn print_stats_test_results( resp_time: Vec, resp_handle_time: Vec, ) { - let mean_req_size = if req_size.len() > 0 {mean(&req_size)} else {0.0}; - let req_std_dev = if req_size.len() > 1 {standard_deviation(&req_size, Some(mean_req_size))} else {0.0}; - let mean_req_time = if req_time.len() > 0 {mean(&req_time)} else {0.0}; - let req_time_std_dev = if req_time.len() > 1 {standard_deviation(&req_time, Some(mean_req_time))} else {0.0}; - let mean_resp_size = if resp_size.len() > 0 {mean(&resp_size)} else {0.0}; - let resp_std_dev = if resp_size.len() > 1 {standard_deviation(&resp_size, Some(mean_resp_size))} else {0.0}; - let mean_resp_time = if resp_time.len() > 0 {mean(&resp_time)} else {0.0}; - let resp_time_std_dev = if resp_time.len() > 1 {standard_deviation(&resp_time, Some(mean_resp_time))} else {0.0}; - let mean_resp_handle_time = if resp_handle_time.len() > 0 {mean(&resp_handle_time)} else {0.0}; - let resp_handle_time_std_dev = if resp_handle_time.len() > 1 {standard_deviation(&resp_handle_time, Some(mean_resp_handle_time))} else {0.0}; + let mean_req_size = if req_size.len() > 0 { + mean(&req_size) + } else { + 0.0 + }; + let req_std_dev = if req_size.len() > 1 { + standard_deviation(&req_size, Some(mean_req_size)) + } else { + 0.0 + }; + let mean_req_time = if req_time.len() > 0 { + mean(&req_time) + } else { + 0.0 + }; + let req_time_std_dev = if req_time.len() > 1 { + standard_deviation(&req_time, Some(mean_req_time)) + } else { + 0.0 + }; + let mean_resp_size = if resp_size.len() > 0 { + mean(&resp_size) + } else { + 0.0 + }; + let resp_std_dev = if resp_size.len() > 1 { + standard_deviation(&resp_size, Some(mean_resp_size)) + } else { + 0.0 + }; + let mean_resp_time = if resp_time.len() > 0 { + mean(&resp_time) + } else { + 0.0 + }; + let resp_time_std_dev = if resp_time.len() > 1 { + standard_deviation(&resp_time, Some(mean_resp_time)) + } else { + 0.0 + }; + let mean_resp_handle_time = if resp_handle_time.len() > 0 { + mean(&resp_handle_time) + } else { + 0.0 + }; + let resp_handle_time_std_dev = if resp_handle_time.len() > 1 { + standard_deviation(&resp_handle_time, Some(mean_resp_handle_time)) + } else { + 0.0 + }; println!("Average request size = {} bytes", mean_req_size); println!("Request size standard deviation = {} bytes", req_std_dev); From ae3fc8f1a2ccc7dba20c02e615617740be3bba90 Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Thu, 20 Oct 2022 17:33:51 -0400 Subject: [PATCH 090/115] Update README --- crates/lox-library/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/lox-library/README.md b/crates/lox-library/README.md index c3cfd4a..009b37d 100644 --- a/crates/lox-library/README.md +++ b/crates/lox-library/README.md @@ -48,8 +48,8 @@ reported results (with larger error margins). To run individual tests with this flag run: ``` - cargo test --release --features=fast -- --nocapture TESTNAME > LOGFILE - ``` +cargo test --release --features=fast -- --nocapture TESTNAME > LOGFILE +``` We have also included the scripts we used to parse the output from each of the Lox tests in the `Parsing-results` directory. For convenience, copy all of the output log files to the `Parsing-results` directory and run `./parse_data.sh`. This is a python script that uses Python 3.8+ and depends on `numpy`, `matplotlib`, and `pandas` which can be installed with `pip3`. @@ -59,8 +59,8 @@ To run all tests in fast mode, output the results to the `Parsing-results` direc ./run_tests_fast ``` -This should take approximately 9 hours to complete. +This takes 5–6 hours to complete on the 2011-era E7-8870 processor we used for the measurements in the paper. Newer processors will likely take less time. Note that with the `fast` feature, it is possible that some tests may only yield 0 or 1 data points, in which case you will see `0` for the times and/or stddevs in the resulting `performance_stats.csv` table for those tests. -Note that: our implementation is coded such that the reachability certificate expires at 00:00 UTC. A workaround has been included in each test to pause if it is too close to this time so the request won't fail. 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). +Note that our implementation is coded such that the reachability certificate expires at 00:00 UTC. A workaround has been included in each test to pause if it is too close to this time so the request won't fail. 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). From b607f3bc3749dff877d49ab104cbd55aa65d1587 Mon Sep 17 00:00:00 2001 From: Vecna Date: Sun, 13 Nov 2022 11:33:57 -0500 Subject: [PATCH 091/115] Make Issuer Keys (de)serializable. --- crates/lox-library/src/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index c74686c..f46e0bf 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -47,6 +47,8 @@ use migration_table::{MigrationTable, MigrationType}; use lazy_static::lazy_static; +use serde::{Serialize, Deserialize}; + lazy_static! { pub static ref CMZ_A: RistrettoPoint = RistrettoPoint::hash_from_bytes::(b"CMZ Generator A"); @@ -56,7 +58,7 @@ lazy_static! { dalek_constants::RISTRETTO_BASEPOINT_TABLE; } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct IssuerPrivKey { x0tilde: Scalar, x: Vec, @@ -77,7 +79,7 @@ impl IssuerPrivKey { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct IssuerPubKey { X: Vec, } From 2cd4d96b73b5f99c9221a6ded19d025bf2cc19d4 Mon Sep 17 00:00:00 2001 From: Vecna Date: Mon, 14 Nov 2022 13:56:13 -0500 Subject: [PATCH 092/115] Make BridgeDb (de)serializable --- crates/lox-library/Cargo.toml | 2 +- crates/lox-library/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index ea76d76..94702a7 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] curve25519-dalek = { package = "curve25519-dalek-ng", version = "3", default-features = false, features = ["serde", "std"] } -ed25519-dalek = "1" +ed25519-dalek = { version = "1", features = ["serde"] } # zkp = { version = "0.8", features = ["debug-transcript"] } zkp = "0.8" bincode = "1" diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index f46e0bf..65709e0 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -106,7 +106,7 @@ impl IssuerPubKey { /// 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)] +#[derive(Debug, Serialize, Deserialize)] pub struct BridgeDb { /// The keypair for signing open invitations keypair: Keypair, From 3945ed5b60624e3d230c9234706b103e44ccce50 Mon Sep 17 00:00:00 2001 From: Vecna Date: Tue, 22 Nov 2022 19:15:09 -0500 Subject: [PATCH 093/115] Make BridgeAuth (de)serializable --- crates/lox-library/src/bridge_table.rs | 4 +++- crates/lox-library/src/dup_filter.rs | 8 +++++--- crates/lox-library/src/lib.rs | 5 +++-- crates/lox-library/src/migration_table.rs | 4 +++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index 6f385a6..aa64d98 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -207,10 +207,12 @@ impl BridgeLine { /// 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. -#[derive(Debug, Default)] +#[serde_as] +#[derive(Debug, Default, Serialize, Deserialize)] pub struct BridgeTable { pub keys: Vec<[u8; 16]>, pub buckets: Vec<[BridgeLine; MAX_BRIDGES_PER_BUCKET]>, + #[serde_as(as = "Vec<[_; ENC_BUCKET_BYTES]>")] pub encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>, /// Individual bridges that are reachable pub reachable: HashMap>, diff --git a/crates/lox-library/src/dup_filter.rs b/crates/lox-library/src/dup_filter.rs index 3a2a797..6f874ba 100644 --- a/crates/lox-library/src/dup_filter.rs +++ b/crates/lox-library/src/dup_filter.rs @@ -8,10 +8,12 @@ use std::cmp::Eq; use std::collections::HashMap; 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. -#[derive(Default, Debug)] -pub struct DupFilter { +#[derive(Default, Debug, Serialize, Deserialize)] +pub struct DupFilter { seen_table: HashMap, } @@ -23,7 +25,7 @@ pub enum SeenType { Seen, } -impl DupFilter { +impl DupFilter { /// Check to see if the id is in the seen table, but do not add it /// to the seen table. Return Seen if it is already in the table, /// Fresh if not. diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 65709e0..0cd9b45 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -47,7 +47,7 @@ use migration_table::{MigrationTable, MigrationType}; use lazy_static::lazy_static; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; lazy_static! { pub static ref CMZ_A: RistrettoPoint = @@ -197,7 +197,7 @@ impl Default for BridgeDb { } /// The bridge authority. This will typically be a singleton object. -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct BridgeAuth { /// The private key for the main Lox credential lox_priv: IssuerPrivKey, @@ -241,6 +241,7 @@ pub struct BridgeAuth { trust_promotion_filter: dup_filter::DupFilter, /// For testing only: offset of the true time to the simulated time + #[serde(skip)] time_offset: time::Duration, } diff --git a/crates/lox-library/src/migration_table.rs b/crates/lox-library/src/migration_table.rs index 86d5aa8..9f98c34 100644 --- a/crates/lox-library/src/migration_table.rs +++ b/crates/lox-library/src/migration_table.rs @@ -22,6 +22,8 @@ use rand::RngCore; use std::collections::HashMap; +use serde::{Deserialize, Serialize}; + use super::bridge_table; use super::cred::Migration; use super::IssuerPrivKey; @@ -57,7 +59,7 @@ impl From for Scalar { } /// The migration table -#[derive(Default, Debug)] +#[derive(Default, Debug, Serialize, Deserialize)] pub struct MigrationTable { pub table: HashMap, pub migration_type: Scalar, From f7002632f730be4276967d5bd83803dd4bfd5c5c Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 16 Jan 2023 22:33:00 -0500 Subject: [PATCH 094/115] Make state serializable for Tor JS bindings Author: onyinyang --- crates/lox-library/src/proto/open_invite.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lox-library/src/proto/open_invite.rs b/crates/lox-library/src/proto/open_invite.rs index 818b32b..461ccbc 100644 --- a/crates/lox-library/src/proto/open_invite.rs +++ b/crates/lox-library/src/proto/open_invite.rs @@ -45,7 +45,7 @@ pub struct Request { } /// The client state for this protocol -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct State { d: Scalar, D: RistrettoPoint, From 9ce2a81fe722be6438a6df567a01b6458922cc4e Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 16 Jan 2023 22:33:01 -0500 Subject: [PATCH 095/115] Make credentials serializable for Tor JS bindings Author: onyinyang --- crates/lox-library/src/cred.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/lox-library/src/cred.rs b/crates/lox-library/src/cred.rs index a0a320d..9f0fc57 100644 --- a/crates/lox-library/src/cred.rs +++ b/crates/lox-library/src/cred.rs @@ -6,6 +6,7 @@ zero-knowledge proof of its correctness (as it does at issuing time). */ use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; +use serde::{Deserialize, Serialize}; /// A migration credential. /// @@ -15,7 +16,7 @@ use curve25519_dalek::scalar::Scalar; /// from a 1-bridge untrusted bucket to a 3-bridge trusted bucket) and 1 /// for blockage migrations (moving buckets because the from_bucket has /// been blocked). -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct Migration { pub P: RistrettoPoint, pub Q: RistrettoPoint, @@ -31,7 +32,7 @@ pub struct Migration { /// 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)] +#[derive(Debug, Serialize, Deserialize)] pub struct Lox { pub P: RistrettoPoint, pub Q: RistrettoPoint, @@ -57,7 +58,7 @@ pub struct Lox { /// That way, people entitled to migrate buckets can receive a Migration /// credential with their new bucket, without the BA learning either /// their old or new buckets. -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct MigrationKey { pub P: RistrettoPoint, pub Q: RistrettoPoint, @@ -73,7 +74,7 @@ pub struct MigrationKey { /// 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. -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct BucketReachability { pub P: RistrettoPoint, pub Q: RistrettoPoint, @@ -89,7 +90,7 @@ pub struct BucketReachability { /// 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. -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct Invitation { pub P: RistrettoPoint, pub Q: RistrettoPoint, From 0e960d915603ffca111e72938ce34ace3febbc37 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 6 Feb 2023 19:47:04 -0500 Subject: [PATCH 096/115] Make all states serializable --- crates/lox-library/src/proto/blockage_migration.rs | 2 +- crates/lox-library/src/proto/check_blockage.rs | 2 +- crates/lox-library/src/proto/issue_invite.rs | 2 +- crates/lox-library/src/proto/level_up.rs | 2 +- crates/lox-library/src/proto/migration.rs | 2 +- crates/lox-library/src/proto/redeem_invite.rs | 2 +- crates/lox-library/src/proto/trust_promotion.rs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/lox-library/src/proto/blockage_migration.rs b/crates/lox-library/src/proto/blockage_migration.rs index 4705535..f1808cd 100644 --- a/crates/lox-library/src/proto/blockage_migration.rs +++ b/crates/lox-library/src/proto/blockage_migration.rs @@ -82,7 +82,7 @@ pub struct Request { piUser: CompactProof, } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct State { d: Scalar, D: RistrettoPoint, diff --git a/crates/lox-library/src/proto/check_blockage.rs b/crates/lox-library/src/proto/check_blockage.rs index 34b3823..323ad01 100644 --- a/crates/lox-library/src/proto/check_blockage.rs +++ b/crates/lox-library/src/proto/check_blockage.rs @@ -73,7 +73,7 @@ pub struct Request { piUser: CompactProof, } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct State { d: Scalar, D: RistrettoPoint, diff --git a/crates/lox-library/src/proto/issue_invite.rs b/crates/lox-library/src/proto/issue_invite.rs index 610de25..0dfde3b 100644 --- a/crates/lox-library/src/proto/issue_invite.rs +++ b/crates/lox-library/src/proto/issue_invite.rs @@ -99,7 +99,7 @@ pub struct Request { piUser: CompactProof, } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct State { d: Scalar, D: RistrettoPoint, diff --git a/crates/lox-library/src/proto/level_up.rs b/crates/lox-library/src/proto/level_up.rs index 5f9bc30..2480b81 100644 --- a/crates/lox-library/src/proto/level_up.rs +++ b/crates/lox-library/src/proto/level_up.rs @@ -137,7 +137,7 @@ pub struct Request { piUser: CompactProof, } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct State { d: Scalar, D: RistrettoPoint, diff --git a/crates/lox-library/src/proto/migration.rs b/crates/lox-library/src/proto/migration.rs index 585f5b5..36ab7d0 100644 --- a/crates/lox-library/src/proto/migration.rs +++ b/crates/lox-library/src/proto/migration.rs @@ -73,7 +73,7 @@ pub struct Request { piUser: CompactProof, } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct State { d: Scalar, D: RistrettoPoint, diff --git a/crates/lox-library/src/proto/redeem_invite.rs b/crates/lox-library/src/proto/redeem_invite.rs index 6692a38..d90fb1d 100644 --- a/crates/lox-library/src/proto/redeem_invite.rs +++ b/crates/lox-library/src/proto/redeem_invite.rs @@ -73,7 +73,7 @@ pub struct Request { piUser: CompactProof, } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct State { d: Scalar, D: RistrettoPoint, diff --git a/crates/lox-library/src/proto/trust_promotion.rs b/crates/lox-library/src/proto/trust_promotion.rs index 9642c8f..18b921a 100644 --- a/crates/lox-library/src/proto/trust_promotion.rs +++ b/crates/lox-library/src/proto/trust_promotion.rs @@ -96,7 +96,7 @@ pub struct Request { piUser: CompactProof, } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct State { d: Scalar, D: RistrettoPoint, From fd4f715ad9c21e367bb3f34ae9e6c3374ecfa968 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Thu, 9 Feb 2023 16:24:43 -0500 Subject: [PATCH 097/115] REVERT BEFORE USING: make BA today function, bridge_table public for testing --- crates/lox-library/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 0cd9b45..c20d895 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -224,7 +224,7 @@ pub struct BridgeAuth { pub bridgedb_pub: PublicKey, /// The bridge table - bridge_table: BridgeTable, + pub bridge_table: BridgeTable, /// The migration tables trustup_migration_table: MigrationTable, @@ -398,7 +398,7 @@ 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) { @@ -406,7 +406,7 @@ impl BridgeAuth { } /// Get today's (real or simulated) date - fn today(&self) -> u32 { + pub fn today(&self) -> u32 { // We will not encounter negative Julian dates (~6700 years ago) // or ones larger than 32 bits (time::OffsetDateTime::now_utc().date() + self.time_offset) From a76fdc98b9389467a78e9eec3e2b6c767fb4336f Mon Sep 17 00:00:00 2001 From: onyinyang Date: Thu, 9 Mar 2023 16:59:20 -0500 Subject: [PATCH 098/115] Add fields to BridgeLine --- crates/lox-library/src/bridge_table.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index aa64d98..b33af2c 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -36,16 +36,20 @@ pub const MAX_BRIDGES_PER_BUCKET: usize = 3; /// level 1) pub const MIN_BUCKET_REACHABILITY: usize = 2; + /// A bridge information line #[serde_as] -#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)] +#[derive(Serialize, Deserialize, Clone, Copy, Hash, Eq, PartialEq, Debug)] pub struct BridgeLine { + /// pluggable transport protocol string as a byte array + pub pt_type: [u8; 25], /// IPv4 or IPv6 address pub addr: [u8; 16], /// port pub port: u16, - /// other protocol information, including pluggable transport, - /// public key, etc. + /// fingerprint as a byte array + pub fingerprint: [u8; 20], + /// other protocol information, including cert and iat mode #[serde_as(as = "[_; BRIDGE_BYTES - 18]")] pub info: [u8; BRIDGE_BYTES - 18], } @@ -68,8 +72,10 @@ impl Default for BridgeLine { /// An "empty" BridgeLine is represented by all zeros fn default() -> Self { Self { + pt_type: [0; 25], addr: [0; 16], port: 0, + fingerprint: [0; 20], info: [0; BRIDGE_BYTES - 18], } } From 00aa9b0ab13137704401a6fc490e1076e9beeadc Mon Sep 17 00:00:00 2001 From: onyinyang Date: Thu, 9 Mar 2023 18:18:02 -0500 Subject: [PATCH 099/115] Revert "Add fields to BridgeLine" This reverts commit 4a014725cdae582401f5d166a722317ed45b8bfe. --- crates/lox-library/src/bridge_table.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index b33af2c..aa64d98 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -36,20 +36,16 @@ pub const MAX_BRIDGES_PER_BUCKET: usize = 3; /// level 1) pub const MIN_BUCKET_REACHABILITY: usize = 2; - /// A bridge information line #[serde_as] -#[derive(Serialize, Deserialize, Clone, Copy, Hash, Eq, PartialEq, Debug)] +#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)] pub struct BridgeLine { - /// pluggable transport protocol string as a byte array - pub pt_type: [u8; 25], /// IPv4 or IPv6 address pub addr: [u8; 16], /// port pub port: u16, - /// fingerprint as a byte array - pub fingerprint: [u8; 20], - /// other protocol information, including cert and iat mode + /// other protocol information, including pluggable transport, + /// public key, etc. #[serde_as(as = "[_; BRIDGE_BYTES - 18]")] pub info: [u8; BRIDGE_BYTES - 18], } @@ -72,10 +68,8 @@ impl Default for BridgeLine { /// An "empty" BridgeLine is represented by all zeros fn default() -> Self { Self { - pt_type: [0; 25], addr: [0; 16], port: 0, - fingerprint: [0; 20], info: [0; BRIDGE_BYTES - 18], } } From 42f5c0e764167d1b339eb6996b3b83a67872ca5f Mon Sep 17 00:00:00 2001 From: onyinyang Date: Fri, 10 Mar 2023 12:02:45 -0500 Subject: [PATCH 100/115] Increase bridge info size --- crates/lox-library/src/bridge_table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index aa64d98..d13accc 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -25,7 +25,7 @@ use std::convert::TryInto; use subtle::ConstantTimeEq; /// Each bridge information line is serialized into this many bytes -pub const BRIDGE_BYTES: usize = 220; +pub const BRIDGE_BYTES: usize = 300; /// The max number of bridges per bucket pub const MAX_BRIDGES_PER_BUCKET: usize = 3; From 366111e28ff55606df842759617af431421444cf Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 20 Mar 2023 12:33:26 -0400 Subject: [PATCH 101/115] Add bridge_update stub --- crates/lox-library/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index c20d895..ff23039 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -309,6 +309,11 @@ impl BridgeAuth { self.bridge_table.spares.insert(bnum); } + pub fn bridge_update(&mut self, bridge: &BridgeLine, bdb: &mut BridgeDb) -> bool { + + false + } + /// Mark a bridge as unreachable /// /// This bridge will be removed from each of the buckets that From f08520de849174943420117943bc3be10bfb89e3 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Thu, 23 Mar 2023 11:00:10 -0400 Subject: [PATCH 102/115] Update function definition for bridge update --- crates/lox-library/src/lib.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index ff23039..ec352b2 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -309,9 +309,31 @@ impl BridgeAuth { self.bridge_table.spares.insert(bnum); } - pub fn bridge_update(&mut self, bridge: &BridgeLine, bdb: &mut BridgeDb) -> bool { - - false + // 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 or else + // or else just replace the info field. + 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 positions = self.bridge_table.reachable.get_key_value(bridge); + if let Some(v) = positions { + println!("Bridge v: {:?} has same IP and Port as bridge {:?}.", v.0, bridge); + let mut w = *v.0; + w.info = bridge.info; + if v.0 == bridge { + println!("Yay"); + println!("Now bridge v: {:?} has all fields the same as bridge {:?}.", v.0, bridge); + }else { + println!("Boo"); + } + res = true; + + } + + res } /// Mark a bridge as unreachable From e257a05c99afe1097bb02a9073f4e581b4a46dc9 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Thu, 23 Mar 2023 13:21:04 -0400 Subject: [PATCH 103/115] Add bridge update --- crates/lox-library/src/lib.rs | 43 +++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index ec352b2..76d94b7 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -315,23 +315,36 @@ impl BridgeAuth { // which will include the IP and Port. Then we can replace the original bridge with the updated bridge or else // or else just replace the info field. 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 positions = self.bridge_table.reachable.get_key_value(bridge); - if let Some(v) = positions { - println!("Bridge v: {:?} has same IP and Port as bridge {:?}.", v.0, bridge); - let mut w = *v.0; - w.info = bridge.info; - if v.0 == bridge { - println!("Yay"); - println!("Now bridge v: {:?} has all fields the same as bridge {:?}.", v.0, bridge); - }else { - println!("Boo"); - } - res = true; - + //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.addr == bridge.addr && reachable_bridge.0.port == bridge.port) { + println!( + "Bridge from table: {:?} has same IP and Port as bridge {:?}!", + reachable_bridge.0, bridge + ); + // Search actual table for bridge + let updating_bridge = self + .bridge_table + .reachable + .get_key_value(&reachable_bridge.0); + if let Some(v) = updating_bridge { + let mut w = *v.0; + w.info = bridge.info; + println!( + "Now bridge v: {:?} matches the passed bridge {:?}?", + v.0, bridge + ); + if v.0 == bridge { + println!("Yay"); + res = true; + } else { + println!("Boo"); + } + } } + } res } From a206917e92aa2765c4cda46b4ebd53e612612931 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 27 Mar 2023 12:36:57 -0400 Subject: [PATCH 104/115] Add update bridge function --- crates/lox-library/src/lib.rs | 49 +++++++++++-------- crates/lox-library/src/tests.rs | 87 ++++++++++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 22 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 76d94b7..3f42317 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -312,37 +312,44 @@ 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 or else - // or else just replace the info field. + // which will include the IP and Port. Then 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. + //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.addr == bridge.addr && reachable_bridge.0.port == bridge.port) { + if reachable_bridge.0.addr == bridge.addr && reachable_bridge.0.port == bridge.port { println!( "Bridge from table: {:?} has same IP and Port as bridge {:?}!", reachable_bridge.0, bridge ); - // Search actual table for bridge - let updating_bridge = self - .bridge_table - .reachable - .get_key_value(&reachable_bridge.0); - if let Some(v) = updating_bridge { - let mut w = *v.0; - w.info = bridge.info; - println!( - "Now bridge v: {:?} matches the passed bridge {:?}?", - v.0, bridge - ); - if v.0 == bridge { - println!("Yay"); - res = true; - } else { - println!("Boo"); + // Now we must remove the old bridge from the table and insert the new bridge in its place + // i.e., in the same bucket and with the same permissions. + let positions = self.bridge_table.reachable.get(&reachable_bridge.0); + if let Some(v) = positions { + for (bucketnum, offset) in v.iter() { + println!("Bucket num: {:?} and offset: {:?}", bucketnum, offset); + assert!( + self.bridge_table.buckets[*bucketnum as usize][*offset] + == reachable_bridge.0 + ); + self.bridge_table.buckets[*bucketnum as usize][*offset] = *bridge; + assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge); + assert!( + self.bridge_table.buckets[*bucketnum as usize][*offset] + != reachable_bridge.0 + ); } } + // We must also remove the old bridge from the reachable bridges table + // and add the new bridge + self.bridge_table.reachable.remove(&reachable_bridge.0); + self.bridge_table + .reachable + .insert(*bridge, reachable_bridge.1); + res = true; } } diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index d69bc22..cedadff 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -1,7 +1,7 @@ /*! Unit tests that require access to the testing-only function BridgeLine::random() or private fields */ -use super::bridge_table::BridgeLine; +use super::bridge_table::{BridgeLine, BRIDGE_BYTES}; use super::proto::*; use super::*; use chrono::{DateTime, NaiveTime, Timelike, Utc}; @@ -598,6 +598,91 @@ fn test_redeem_invite() { println!("bob_cred = {:?}", bob_cred); } +#[test] +fn test_update_bridge() { + let mut th = TestHarness::new(); + // Add new bridge to table with known values, + // check that I can find and update the values and that everything else stays the same + + // Create 3 bridges to test harness + let bucket = [ + BridgeLine::random(), + BridgeLine::random(), + BridgeLine::random(), + ]; + // Store first bridgeline to update later + let bridgeline_to_update = bucket[0]; + // Created changed info for bridgeline to be updated to + let updated_info = bucket[0]; + let infostr: String = format!( + "type={} blocked_in={:?} protocol={} fingerprint={} distribution={}", + "obfs2 test bridge".to_string(), + {}, + "obfs2".to_string(), + "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCD".to_string(), + "moat".to_string(), + ); + let mut updated_info_bytes: [u8; BRIDGE_BYTES - 18] = [0; BRIDGE_BYTES - 18]; + + updated_info_bytes[..infostr.len()].copy_from_slice(infostr.as_bytes()); + + let updated_bridgeline = BridgeLine { + addr: bridgeline_to_update.addr, + port: bridgeline_to_update.port, + info: updated_info_bytes, + }; + + assert!( + updated_bridgeline.addr == bridgeline_to_update.addr, + "Bridge entering the bridgepool {:?} did not have the same IP as the updating bridge {:?}", + bridgeline_to_update, + updated_bridgeline.addr + ); + assert!(updated_bridgeline.port == bridgeline_to_update.port, "Bridge entering the bridgepool {:?} did not have the same port as the updating bridge {:?}", bridgeline_to_update, updated_bridgeline.port); + assert!(updated_bridgeline.info != bridgeline_to_update.info); + println!( + "Bridge entering the bridgepool {:?} has different info than the updating bridge {:?}", + bridgeline_to_update.info, updated_bridgeline.info + ); + assert!(updated_bridgeline != bridgeline_to_update); + println!("The two bridgelines are not equal before the update"); + + // Add 3 bridges to test harness + th.ba.add_openinv_bridges(bucket, &mut th.bdb); + + println!("Before update spares = {:?}", th.ba.bridge_table.spares); + println!( + "Before update tmig = {:?}", + th.ba.trustup_migration_table.table + ); + println!( + "Before update bmig = {:?}", + th.ba.blockage_migration_table.table + ); + println!("Before update openinv = {:?}\n", th.bdb.openinv_buckets); + + // Update the info of a bridge with matching IP and Port to a bridge in the bridge table + let result = th.ba.bridge_update(&updated_bridgeline); + assert!(result, "Bridge failed to update successfully!!"); + let found_bridge = th + .ba + .bridge_table + .reachable + .get_key_value(&updated_bridgeline); + assert!(*found_bridge.unwrap().0 != bridgeline_to_update); + assert!(*found_bridge.unwrap().0 == updated_bridgeline); + println!("After update spares = {:?}", th.ba.bridge_table.spares); + println!( + "After update tmig = {:?}", + th.ba.trustup_migration_table.table + ); + println!( + "After update bmig = {:?}", + th.ba.blockage_migration_table.table + ); + println!("After update openinv = {:?}\n", th.bdb.openinv_buckets); +} + #[test] fn test_mark_unreachable() { let mut th = TestHarness::new(); From 362996c4f7cfed64a149a3846319b1b95b0d5f24 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 3 Apr 2023 11:47:11 -0400 Subject: [PATCH 105/115] Add fingerprint field to Bridgeline --- crates/lox-library/src/bridge_table.rs | 25 ++++++++++++++++--------- crates/lox-library/src/lib.rs | 20 +++++++++++++++++--- crates/lox-library/src/tests.rs | 13 ++++++------- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index d13accc..6a22cf3 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -25,7 +25,7 @@ use std::convert::TryInto; use subtle::ConstantTimeEq; /// Each bridge information line is serialized into this many bytes -pub const BRIDGE_BYTES: usize = 300; +pub const BRIDGE_BYTES: usize = 260; /// The max number of bridges per bucket pub const MAX_BRIDGES_PER_BUCKET: usize = 3; @@ -44,10 +44,13 @@ pub struct BridgeLine { pub addr: [u8; 16], /// port pub port: u16, + /// fingerprint + #[serde_as(as = "[_; 40]")] + pub fingerprint: [u8; 40], /// other protocol information, including pluggable transport, /// public key, etc. - #[serde_as(as = "[_; BRIDGE_BYTES - 18]")] - pub info: [u8; BRIDGE_BYTES - 18], + #[serde_as(as = "[_; BRIDGE_BYTES - 58]")] + pub info: [u8; BRIDGE_BYTES - 58], } /// A bucket contains MAX_BRIDGES_PER_BUCKET bridges plus the @@ -70,7 +73,8 @@ impl Default for BridgeLine { Self { addr: [0; 16], port: 0, - info: [0; BRIDGE_BYTES - 18], + fingerprint: [0; 40], + info: [0; BRIDGE_BYTES - 58], } } } @@ -81,7 +85,8 @@ impl BridgeLine { let mut res: [u8; BRIDGE_BYTES] = [0; BRIDGE_BYTES]; res[0..16].copy_from_slice(&self.addr); res[16..18].copy_from_slice(&self.port.to_be_bytes()); - res[18..].copy_from_slice(&self.info); + res[18..58].copy_from_slice(&self.fingerprint); + res[58..].copy_from_slice(&self.info); res } /// Decode a BridgeLine from a byte array @@ -89,7 +94,8 @@ impl BridgeLine { let mut res: Self = Default::default(); res.addr.copy_from_slice(&data[0..16]); res.port = u16::from_be_bytes(data[16..18].try_into().unwrap()); - res.info.copy_from_slice(&data[18..]); + res.fingerprint.copy_from_slice(&data[18..58]); + res.info.copy_from_slice(&data[58..]); res } /// Encode a bucket to a byte array, including a Bucket Reachability @@ -188,13 +194,14 @@ impl BridgeLine { let ports: [u16; 4] = [443, 4433, 8080, 43079]; let portidx = (rng.next_u32() % 4) as usize; res.port = ports[portidx]; - let mut fingerprint: [u8; 20] = [0; 20]; + let mut fingerprint: [u8; 40] = [0; 40]; + rng.fill_bytes(&mut fingerprint); let mut cert: [u8; 52] = [0; 52]; rng.fill_bytes(&mut fingerprint); + res.fingerprint[0..40].copy_from_slice(&fingerprint); rng.fill_bytes(&mut cert); let infostr: String = format!( - "obfs4 {} cert={} iat-mode=0", - hex_fmt::HexFmt(fingerprint), + "obfs4 cert={}, iat-mode=0", base64::encode_config(cert, base64::STANDARD_NO_PAD) ); res.info[..infostr.len()].copy_from_slice(infostr.as_bytes()); diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 3f42317..5c78e30 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -309,6 +309,17 @@ impl BridgeAuth { self.bridge_table.spares.insert(bnum); } + pub fn sync_table(&mut self) { + + // Create a hashtable (?) of bridges in the lox distributor from new resources + // accept the hashtable and recreate the bridge table from the hash table here + // using existing reachable bridges, other table checks and placements from existing bridge table + // If bridges are in reachable bridges, put them in the table with their Vec + // How to check for bridges that aren't there/are extra? + // After going through the update, make sure bridges in the table are the same and deal with discrepencies + // This will be the bad/annoying part + } + // 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 @@ -316,11 +327,11 @@ impl BridgeAuth { // 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. + //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.addr == bridge.addr && reachable_bridge.0.port == bridge.port { + if reachable_bridge.0.fingerprint == bridge.fingerprint { println!( "Bridge from table: {:?} has same IP and Port as bridge {:?}!", reachable_bridge.0, bridge @@ -342,6 +353,9 @@ impl BridgeAuth { != reachable_bridge.0 ); } + res = true; + } else { + return res; } // We must also remove the old bridge from the reachable bridges table // and add the new bridge @@ -349,7 +363,7 @@ impl BridgeAuth { self.bridge_table .reachable .insert(*bridge, reachable_bridge.1); - res = true; + return res; } } diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index cedadff..5ca62d9 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -615,30 +615,29 @@ fn test_update_bridge() { // Created changed info for bridgeline to be updated to let updated_info = bucket[0]; let infostr: String = format!( - "type={} blocked_in={:?} protocol={} fingerprint={} distribution={}", + "type={} blocked_in={:?} protocol={} distribution={}", "obfs2 test bridge".to_string(), {}, "obfs2".to_string(), - "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCD".to_string(), "moat".to_string(), ); - let mut updated_info_bytes: [u8; BRIDGE_BYTES - 18] = [0; BRIDGE_BYTES - 18]; + let mut updated_info_bytes: [u8; BRIDGE_BYTES - 58] = [0; BRIDGE_BYTES - 58]; updated_info_bytes[..infostr.len()].copy_from_slice(infostr.as_bytes()); let updated_bridgeline = BridgeLine { addr: bridgeline_to_update.addr, port: bridgeline_to_update.port, + fingerprint: bridgeline_to_update.fingerprint, info: updated_info_bytes, }; assert!( - updated_bridgeline.addr == bridgeline_to_update.addr, - "Bridge entering the bridgepool {:?} did not have the same IP as the updating bridge {:?}", + updated_bridgeline.fingerprint == bridgeline_to_update.fingerprint, + "Bridge entering the bridgepool {:?} did not have the same fingerprint as the updating bridge {:?}", bridgeline_to_update, - updated_bridgeline.addr + updated_bridgeline.fingerprint ); - assert!(updated_bridgeline.port == bridgeline_to_update.port, "Bridge entering the bridgepool {:?} did not have the same port as the updating bridge {:?}", bridgeline_to_update, updated_bridgeline.port); assert!(updated_bridgeline.info != bridgeline_to_update.info); println!( "Bridge entering the bridgepool {:?} has different info than the updating bridge {:?}", From a3a693d45a1bbab0114d754b6f2a505f53b96a94 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 3 Apr 2023 12:06:20 -0400 Subject: [PATCH 106/115] Revise bridge bytes size to 300 --- crates/lox-library/src/bridge_table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index 6a22cf3..f291973 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -25,7 +25,7 @@ use std::convert::TryInto; use subtle::ConstantTimeEq; /// Each bridge information line is serialized into this many bytes -pub const BRIDGE_BYTES: usize = 260; +pub const BRIDGE_BYTES: usize = 300; /// The max number of bridges per bucket pub const MAX_BRIDGES_PER_BUCKET: usize = 3; From 11d4678be828bf59f283d1a75cd13a2bb9911bf1 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Tue, 4 Apr 2023 18:39:28 -0400 Subject: [PATCH 107/115] Update fingerprint to match UID from rdsys --- crates/lox-library/src/bridge_table.rs | 24 ++++++++++-------------- crates/lox-library/src/lib.rs | 6 +++++- crates/lox-library/src/tests.rs | 8 ++++---- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index f291973..a9070a4 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -45,12 +45,11 @@ pub struct BridgeLine { /// port pub port: u16, /// fingerprint - #[serde_as(as = "[_; 40]")] - pub fingerprint: [u8; 40], + pub uid_fingerprint: u64, /// other protocol information, including pluggable transport, /// public key, etc. - #[serde_as(as = "[_; BRIDGE_BYTES - 58]")] - pub info: [u8; BRIDGE_BYTES - 58], + #[serde_as(as = "[_; BRIDGE_BYTES - 26]")] + pub info: [u8; BRIDGE_BYTES - 26], } /// A bucket contains MAX_BRIDGES_PER_BUCKET bridges plus the @@ -73,8 +72,8 @@ impl Default for BridgeLine { Self { addr: [0; 16], port: 0, - fingerprint: [0; 40], - info: [0; BRIDGE_BYTES - 58], + uid_fingerprint: 0, + info: [0; BRIDGE_BYTES - 26], } } } @@ -85,8 +84,8 @@ impl BridgeLine { let mut res: [u8; BRIDGE_BYTES] = [0; BRIDGE_BYTES]; res[0..16].copy_from_slice(&self.addr); res[16..18].copy_from_slice(&self.port.to_be_bytes()); - res[18..58].copy_from_slice(&self.fingerprint); - res[58..].copy_from_slice(&self.info); + res[18..26].copy_from_slice(&self.uid_fingerprint.to_be_bytes()); + res[26..].copy_from_slice(&self.info); res } /// Decode a BridgeLine from a byte array @@ -94,8 +93,8 @@ impl BridgeLine { let mut res: Self = Default::default(); res.addr.copy_from_slice(&data[0..16]); res.port = u16::from_be_bytes(data[16..18].try_into().unwrap()); - res.fingerprint.copy_from_slice(&data[18..58]); - res.info.copy_from_slice(&data[58..]); + res.uid_fingerprint = u64::from_be_bytes(data[18..26].try_into().unwrap()); + res.info.copy_from_slice(&data[26..]); res } /// Encode a bucket to a byte array, including a Bucket Reachability @@ -194,11 +193,8 @@ impl BridgeLine { let ports: [u16; 4] = [443, 4433, 8080, 43079]; let portidx = (rng.next_u32() % 4) as usize; res.port = ports[portidx]; - let mut fingerprint: [u8; 40] = [0; 40]; - rng.fill_bytes(&mut fingerprint); + res.uid_fingerprint = rng.next_u64(); let mut cert: [u8; 52] = [0; 52]; - rng.fill_bytes(&mut fingerprint); - res.fingerprint[0..40].copy_from_slice(&fingerprint); rng.fill_bytes(&mut cert); let infostr: String = format!( "obfs4 cert={}, iat-mode=0", diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 5c78e30..f609d59 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -331,7 +331,7 @@ impl BridgeAuth { let reachable_bridges = self.bridge_table.reachable.clone(); for reachable_bridge in reachable_bridges { - if reachable_bridge.0.fingerprint == bridge.fingerprint { + if reachable_bridge.0.uid_fingerprint == bridge.uid_fingerprint { println!( "Bridge from table: {:?} has same IP and Port as bridge {:?}!", reachable_bridge.0, bridge @@ -366,6 +366,10 @@ impl BridgeAuth { return res; } } + if !res { + // Assume the bridge is new and should be added to unallocated bridges or else a new bucket + + } res } diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 5ca62d9..885980c 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -621,22 +621,22 @@ fn test_update_bridge() { "obfs2".to_string(), "moat".to_string(), ); - let mut updated_info_bytes: [u8; BRIDGE_BYTES - 58] = [0; BRIDGE_BYTES - 58]; + let mut updated_info_bytes: [u8; BRIDGE_BYTES - 26] = [0; BRIDGE_BYTES - 26]; updated_info_bytes[..infostr.len()].copy_from_slice(infostr.as_bytes()); let updated_bridgeline = BridgeLine { addr: bridgeline_to_update.addr, port: bridgeline_to_update.port, - fingerprint: bridgeline_to_update.fingerprint, + uid_fingerprint: bridgeline_to_update.uid_fingerprint, info: updated_info_bytes, }; assert!( - updated_bridgeline.fingerprint == bridgeline_to_update.fingerprint, + updated_bridgeline.uid_fingerprint == bridgeline_to_update.uid_fingerprint, "Bridge entering the bridgepool {:?} did not have the same fingerprint as the updating bridge {:?}", bridgeline_to_update, - updated_bridgeline.fingerprint + updated_bridgeline.uid_fingerprint ); assert!(updated_bridgeline.info != bridgeline_to_update.info); println!( From 83c791680502818df1f2e5d552d7c239f187f87b Mon Sep 17 00:00:00 2001 From: onyinyang Date: Thu, 4 May 2023 18:10:50 -0400 Subject: [PATCH 108/115] Added bridge replacement --- crates/lox-library/src/bridge_table.rs | 11 ++- crates/lox-library/src/lib.rs | 120 ++++++++++++++++++++++++- 2 files changed, 127 insertions(+), 4 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index a9070a4..ec2e0f6 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -224,8 +224,17 @@ pub struct BridgeTable { /// them. When a new Migration credential is needed, a bucket is /// removed from this set and used for that purpose. pub spares: HashSet, + /// bucket ids of "recyclable" buckets. These buckets have not been handed out + /// to users, nor do they have any Migration credentials pointing to + /// them. When a single bridge is needed and there are no more readily available bridges, + /// bridges are taken from a bucket of hot spares, making the unallocated spare bucket empty + /// but still useable as it has not been handed out previously. + pub recyclable: HashSet, + /// 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 + /// In that case, a spare bucket will be removed from the set of spare bridges. One + pub unallocated_bridges: Vec, /// The date the buckets were last encrypted to make the encbucket. - /// /// The encbucket must be rebuilt each day so that the Bucket /// Reachability credentials in the buckets can be refreshed. pub date_last_enc: u32, diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index f609d59..81e9d6b 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -366,11 +366,125 @@ impl BridgeAuth { return res; } } - if !res { - // Assume the bridge is new and should be added to unallocated bridges or else a new bucket + // If this is returned, we assume that the bridge wasn't found in the bridge table + // and therefore should be treated as a "new bridge" + res + } + pub fn bridge_replace( + &mut self, + bridge: &BridgeLine, + available_bridge: Option<&BridgeLine>, + bdb: &mut BridgeDb, + ) -> bool { + let mut res: bool = false; + let reachable_bridges = &self.bridge_table.reachable.clone(); + if let Some(positions) = reachable_bridges.get(bridge) { + for (bucketnum, offset) in positions.iter() { + // Remove the bridge from the bucket + assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge); + self.bridge_table.reachable.remove(bridge); + if available_bridge.is_some() { + self.bridge_table.buckets[*bucketnum as usize][*offset] = + *available_bridge.unwrap(); + // Remove the bridge from the reachable bridges and add new bridge + self.bridge_table + .reachable + .insert(*available_bridge.unwrap(), positions.clone()); + res = true + } else if !self.bridge_table.unallocated_bridges.is_empty() { + self.bridge_table.buckets[*bucketnum as usize][*offset] = + self.bridge_table.unallocated_bridges.pop().unwrap(); + // Remove the bridge from the reachable bridges and add new bridge + self.bridge_table.reachable.insert( + self.bridge_table.unallocated_bridges.pop().unwrap(), + positions.clone(), + ); + res = true + } else if !self.bridge_table.spares.is_empty() { + // Get the first spare and remove it from the spares + // set. + let spare = *self.bridge_table.spares.iter().next().unwrap(); + self.bridge_table.spares.remove(&spare); + // Indicate the removed bucket as a recyclable bucket + self.bridge_table.recyclable.insert(spare); + // Get the actual bridges from the spare bucket + let mut replacement: &BridgeLine = &BridgeLine::default(); + // Make the first spare the replacement bridge, add the others to the set of + // unallocated_bridges + let spare_bucket = self.bridge_table.buckets[spare as usize].clone(); + for spare_bridge in spare_bucket.iter() { + if replacement.port > 0 { + self.bridge_table.unallocated_bridges.push(*spare_bridge); + } else { + replacement = spare_bridge; + } + } + self.bridge_table.buckets[*bucketnum as usize][*offset] = *replacement; + self.bridge_table + .reachable + .insert(*replacement, positions.clone()); + res = true + } + // If there are no available bridges that can be assigned here, the only thing + // that can be done is return an indication that updating the gone bridge + // didn't work. + + // Now we should check that the bucket hasn't become "blocked" due to having no available + // bridges + if !res { + // Count how many bridges in this bucket are reachable + let numreachable = self.bridge_table.buckets[*bucketnum as usize] + .iter() + .filter(|br| self.bridge_table.reachable.get(br).is_some()) + .count(); + + // Is this bucket an open-invitation bucket? + if bdb.openinv_buckets.contains(bucketnum) { + bdb.openinv_buckets.remove(bucketnum); + self.trustup_migration_table.table.remove(bucketnum); + continue; + } + + // Has the bucket fallen below the + // threshold? + if numreachable == MIN_BUCKET_REACHABILITY { + // This bucket is now unreachable. Get a spare bucket + if self.bridge_table.spares.is_empty() { + // Uh, oh. No spares available. Just delete any + // migrations leading to this bucket. + self.trustup_migration_table + .table + .retain(|_, &mut v| v != *bucketnum); + self.blockage_migration_table + .table + .retain(|_, &mut v| v != *bucketnum); + } else { + // Get the first spare and remove it from the spares + // set. + let spare = *self.bridge_table.spares.iter().next().unwrap(); + self.bridge_table.spares.remove(&spare); + // Add a blockage migration from this bucket to the spare + self.blockage_migration_table + .table + .insert(*bucketnum, spare); + // Remove any trust upgrade migrations to this + // bucket + self.trustup_migration_table + .table + .retain(|_, &mut v| v != *bucketnum); + // Change any blockage migrations with this bucket + // as the destination to the spare + for (_, v) in self.blockage_migration_table.table.iter_mut() { + if *v == *bucketnum { + *v = spare; + } + } + } + } + } + } } - res } From 508eaf3bdd193ddb6d4ef5e77089bf2bbad3b18c Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 8 May 2023 19:44:36 -0400 Subject: [PATCH 109/115] Add functions to recycle and allocate extra bridges --- crates/lox-library/src/bridge_table.rs | 19 ++++++++++++++++ crates/lox-library/src/lib.rs | 31 ++++++++++++++++++++++++-- crates/lox-library/src/tests.rs | 21 +++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/crates/lox-library/src/bridge_table.rs b/crates/lox-library/src/bridge_table.rs index ec2e0f6..1750d7b 100644 --- a/crates/lox-library/src/bridge_table.rs +++ b/crates/lox-library/src/bridge_table.rs @@ -249,6 +249,25 @@ impl BridgeTable { self.buckets.len() } + pub fn recycle_bucket(&mut self, bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET], index: u32) { + // Pick a random key to encrypt this bucket + let mut rng = rand::thread_rng(); + let mut key: [u8; 16] = [0; 16]; + rng.fill_bytes(&mut key); + self.keys[index as usize] = key; + self.buckets[index as usize] = *bucket; + for (i, b) in bucket.iter().enumerate() { + if b.port > 0 { + if let Some(v) = self.reachable.get_mut(b) { + v.push((index, i)); + } else { + let v = vec![(index, i)]; + self.reachable.insert(*b, v); + } + } + } + } + /// Append a new bucket to the bridge table, returning its index pub fn new_bucket(&mut self, bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET]) -> u32 { // Pick a random key to encrypt this bucket diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 81e9d6b..5fc9eb7 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -293,7 +293,14 @@ impl BridgeAuth { bridges: [BridgeLine; MAX_BRIDGES_PER_BUCKET], bdb: &mut BridgeDb, ) { - let bnum = self.bridge_table.new_bucket(&bridges); + let bnum: u32; + if self.bridge_table.recyclable.is_empty() { + bnum = self.bridge_table.new_bucket(&bridges); + } else { + bnum = *self.bridge_table.recyclable.iter().next().unwrap(); + self.bridge_table.recyclable.remove(&bnum); + self.bridge_table.recycle_bucket(&bridges, bnum) + } let mut single = [BridgeLine::default(); MAX_BRIDGES_PER_BUCKET]; for b in bridges.iter() { single[0] = *b; @@ -305,7 +312,14 @@ impl BridgeAuth { /// Insert a hot spare bucket of bridges pub fn add_spare_bucket(&mut self, bucket: [BridgeLine; MAX_BRIDGES_PER_BUCKET]) { - let bnum = self.bridge_table.new_bucket(&bucket); + let bnum: u32; + if self.bridge_table.recyclable.is_empty() { + bnum = self.bridge_table.new_bucket(&bucket); + } else { + bnum = *self.bridge_table.recyclable.iter().next().unwrap(); + self.bridge_table.recyclable.remove(&bnum); + self.bridge_table.recycle_bucket(&bucket, bnum) + } self.bridge_table.spares.insert(bnum); } @@ -320,6 +334,19 @@ impl BridgeAuth { // This will be the bad/annoying part } + pub fn allocate_bridges(&mut self, distributor_bridges: &mut Vec, bdb: &mut BridgeDb) { + while let Some(bridge) = distributor_bridges.iter().next_back() { + self.bridge_table.unallocated_bridges.push(*bridge) + } + while self.bridge_table.unallocated_bridges.len() >= MAX_BRIDGES_PER_BUCKET { + let mut bucket = [BridgeLine::default(); MAX_BRIDGES_PER_BUCKET]; + for i in 0..MAX_BRIDGES_PER_BUCKET { + bucket[i] = self.bridge_table.unallocated_bridges.pop().unwrap(); + } + self.add_openinv_bridges(bucket, bdb); + } + } + // 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 diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 885980c..b9c5d9e 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -682,6 +682,27 @@ fn test_update_bridge() { println!("After update openinv = {:?}\n", th.bdb.openinv_buckets); } +#[test] +fn test_bridge_replace() { + // TODO + let mut th = TestHarness::new(); + // Add new bridge to table with known values, + // check that I can find and update the values and that everything else stays the same + + // Create 3 bridges to test harness + let bucket = [ + BridgeLine::random(), + BridgeLine::random(), + BridgeLine::random(), + ]; + +} + +#[test] +fn test_allocate_bridges() { + // TODO +} + #[test] fn test_mark_unreachable() { let mut th = TestHarness::new(); From 0d317cea8c23ff8f2b143270983ef35de15c3db7 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Thu, 11 May 2023 16:51:24 -0400 Subject: [PATCH 110/115] Fix replace bridge to align with changes to lox-distributor --- crates/lox-library/src/lib.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 5fc9eb7..af56ecb 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -408,9 +408,7 @@ impl BridgeAuth { let reachable_bridges = &self.bridge_table.reachable.clone(); if let Some(positions) = reachable_bridges.get(bridge) { for (bucketnum, offset) in positions.iter() { - // Remove the bridge from the bucket assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge); - self.bridge_table.reachable.remove(bridge); if available_bridge.is_some() { self.bridge_table.buckets[*bucketnum as usize][*offset] = *available_bridge.unwrap(); @@ -418,6 +416,8 @@ impl BridgeAuth { self.bridge_table .reachable .insert(*available_bridge.unwrap(), positions.clone()); + // Remove the bridge from the bucket + self.bridge_table.reachable.remove(bridge); res = true } else if !self.bridge_table.unallocated_bridges.is_empty() { self.bridge_table.buckets[*bucketnum as usize][*offset] = @@ -427,6 +427,8 @@ impl BridgeAuth { self.bridge_table.unallocated_bridges.pop().unwrap(), positions.clone(), ); + // Remove the bridge from the bucket + self.bridge_table.reachable.remove(bridge); res = true } else if !self.bridge_table.spares.is_empty() { // Get the first spare and remove it from the spares @@ -451,11 +453,16 @@ impl BridgeAuth { self.bridge_table .reachable .insert(*replacement, positions.clone()); + // Remove the bridge from the bucket + self.bridge_table.reachable.remove(bridge); res = true } // If there are no available bridges that can be assigned here, the only thing // that can be done is return an indication that updating the gone bridge // didn't work. + // In this case, we do not mark the bridge as unreachable or remove it from the + // reachable bridges so that we can still find it when a new bridge does become available + // Now we should check that the bucket hasn't become "blocked" due to having no available // bridges From 6bff64f2830540db0b2a3f99e975adcf66384cda Mon Sep 17 00:00:00 2001 From: onyinyang Date: Wed, 10 May 2023 20:26:08 -0400 Subject: [PATCH 111/115] Adds replace_bridge test and fixes bugs in the function --- crates/lox-library/src/lib.rs | 257 ++++++++++++++------------------ crates/lox-library/src/tests.rs | 187 ++++++++++++++++++++--- 2 files changed, 280 insertions(+), 164 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index af56ecb..a82b3da 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -334,7 +334,11 @@ impl BridgeAuth { // This will be the bad/annoying part } - pub fn allocate_bridges(&mut self, distributor_bridges: &mut Vec, bdb: &mut BridgeDb) { + pub fn allocate_bridges( + &mut self, + distributor_bridges: &mut Vec, + bdb: &mut BridgeDb, + ) { while let Some(bridge) = distributor_bridges.iter().next_back() { self.bridge_table.unallocated_bridges.push(*bridge) } @@ -407,9 +411,9 @@ impl BridgeAuth { let mut res: bool = false; let reachable_bridges = &self.bridge_table.reachable.clone(); if let Some(positions) = reachable_bridges.get(bridge) { - for (bucketnum, offset) in positions.iter() { - assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge); - if available_bridge.is_some() { + if available_bridge.is_some() { + for (bucketnum, offset) in positions.iter() { + assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge); self.bridge_table.buckets[*bucketnum as usize][*offset] = *available_bridge.unwrap(); // Remove the bridge from the reachable bridges and add new bridge @@ -419,105 +423,53 @@ impl BridgeAuth { // Remove the bridge from the bucket self.bridge_table.reachable.remove(bridge); res = true - } else if !self.bridge_table.unallocated_bridges.is_empty() { - self.bridge_table.buckets[*bucketnum as usize][*offset] = - self.bridge_table.unallocated_bridges.pop().unwrap(); - // Remove the bridge from the reachable bridges and add new bridge - self.bridge_table.reachable.insert( - self.bridge_table.unallocated_bridges.pop().unwrap(), - positions.clone(), - ); - // Remove the bridge from the bucket - self.bridge_table.reachable.remove(bridge); - res = true - } else if !self.bridge_table.spares.is_empty() { - // Get the first spare and remove it from the spares - // set. - let spare = *self.bridge_table.spares.iter().next().unwrap(); - self.bridge_table.spares.remove(&spare); - // Indicate the removed bucket as a recyclable bucket - self.bridge_table.recyclable.insert(spare); - // Get the actual bridges from the spare bucket - let mut replacement: &BridgeLine = &BridgeLine::default(); - // Make the first spare the replacement bridge, add the others to the set of - // unallocated_bridges - let spare_bucket = self.bridge_table.buckets[spare as usize].clone(); - for spare_bridge in spare_bucket.iter() { - if replacement.port > 0 { - self.bridge_table.unallocated_bridges.push(*spare_bridge); - } else { - replacement = spare_bridge; - } - } + } + } else if !self.bridge_table.unallocated_bridges.is_empty() { + let replacement = &self.bridge_table.unallocated_bridges.pop().unwrap(); + for (bucketnum, offset) in positions.iter() { self.bridge_table.buckets[*bucketnum as usize][*offset] = *replacement; self.bridge_table .reachable .insert(*replacement, positions.clone()); // Remove the bridge from the bucket self.bridge_table.reachable.remove(bridge); - res = true } - // If there are no available bridges that can be assigned here, the only thing - // that can be done is return an indication that updating the gone bridge - // didn't work. - // In this case, we do not mark the bridge as unreachable or remove it from the - // reachable bridges so that we can still find it when a new bridge does become available - - - // Now we should check that the bucket hasn't become "blocked" due to having no available - // bridges - if !res { - // Count how many bridges in this bucket are reachable - let numreachable = self.bridge_table.buckets[*bucketnum as usize] - .iter() - .filter(|br| self.bridge_table.reachable.get(br).is_some()) - .count(); - - // Is this bucket an open-invitation bucket? - if bdb.openinv_buckets.contains(bucketnum) { - bdb.openinv_buckets.remove(bucketnum); - self.trustup_migration_table.table.remove(bucketnum); - continue; - } - - // Has the bucket fallen below the - // threshold? - if numreachable == MIN_BUCKET_REACHABILITY { - // This bucket is now unreachable. Get a spare bucket - if self.bridge_table.spares.is_empty() { - // Uh, oh. No spares available. Just delete any - // migrations leading to this bucket. - self.trustup_migration_table - .table - .retain(|_, &mut v| v != *bucketnum); - self.blockage_migration_table - .table - .retain(|_, &mut v| v != *bucketnum); - } else { - // Get the first spare and remove it from the spares - // set. - let spare = *self.bridge_table.spares.iter().next().unwrap(); - self.bridge_table.spares.remove(&spare); - // Add a blockage migration from this bucket to the spare - self.blockage_migration_table - .table - .insert(*bucketnum, spare); - // Remove any trust upgrade migrations to this - // bucket - self.trustup_migration_table - .table - .retain(|_, &mut v| v != *bucketnum); - // Change any blockage migrations with this bucket - // as the destination to the spare - for (_, v) in self.blockage_migration_table.table.iter_mut() { - if *v == *bucketnum { - *v = spare; - } - } - } + res = true + } else if !self.bridge_table.spares.is_empty() { + // Get the first spare and remove it from the spares set. + let spare = *self.bridge_table.spares.iter().next().unwrap(); + self.bridge_table.spares.remove(&spare); + // Indicate the removed bucket as a recyclable bucket + self.bridge_table.recyclable.insert(spare); + // Get the actual bridges from the spare bucket + let spare_bucket = self.bridge_table.buckets[spare as usize].clone(); + let mut replacement: &BridgeLine = &BridgeLine::default(); + // Make the first spare the replacement bridge, add the others to the set of + // unallocated_bridges + for spare_bridge in spare_bucket.iter() { + if replacement.port > 0 { + self.bridge_table.unallocated_bridges.push(*spare_bridge); + // Mark bucket as unreachable while it is unallocated + self.bridge_table.reachable.remove(spare_bridge); + } else { + replacement = spare_bridge; } } + for (bucketnum, offset) in positions.iter() { + self.bridge_table.buckets[*bucketnum as usize][*offset] = *replacement; + self.bridge_table + .reachable + .insert(*replacement, positions.clone()); + // Remove the bridge from the bucket + self.bridge_table.reachable.remove(bridge); + } + res = true } + // If there are no available bridges that can be assigned here, the only thing + // that can be done is return an indication that updating the gone bridge + // didn't work. + // In this case, we do not mark the bridge as unreachable or remove it from the + // reachable bridges so that we can still find it when a new bridge does become available } res } @@ -538,69 +490,80 @@ impl BridgeAuth { /// there was none available. pub fn bridge_unreachable(&mut self, bridge: &BridgeLine, bdb: &mut BridgeDb) -> bool { let mut res: bool = true; - let positions = self.bridge_table.reachable.get(bridge); - if let Some(v) = positions { - for (bucketnum, offset) in v.iter() { - // Count how many bridges in this bucket are reachable - let numreachable = self.bridge_table.buckets[*bucketnum as usize] - .iter() - .filter(|br| self.bridge_table.reachable.get(br).is_some()) - .count(); + if self.bridge_table.unallocated_bridges.contains(bridge) { + let index = self + .bridge_table + .unallocated_bridges + .iter() + .position(|&b| b == *bridge) + .unwrap(); + self.bridge_table.unallocated_bridges.remove(index); + res = true; + } else { + let positions = self.bridge_table.reachable.get(bridge); + if let Some(v) = positions { + for (bucketnum, offset) in v.iter() { + // Count how many bridges in this bucket are reachable + let numreachable = self.bridge_table.buckets[*bucketnum as usize] + .iter() + .filter(|br| self.bridge_table.reachable.get(br).is_some()) + .count(); - // Remove the bridge from the bucket - assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge); - self.bridge_table.buckets[*bucketnum as usize][*offset] = BridgeLine::default(); + // Remove the bridge from the bucket + assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge); + self.bridge_table.buckets[*bucketnum as usize][*offset] = BridgeLine::default(); - // Is this bucket an open-invitation bucket? - if bdb.openinv_buckets.contains(bucketnum) { - bdb.openinv_buckets.remove(bucketnum); - self.trustup_migration_table.table.remove(bucketnum); - continue; - } + // Is this bucket an open-invitation bucket? + if bdb.openinv_buckets.contains(bucketnum) { + bdb.openinv_buckets.remove(bucketnum); + self.trustup_migration_table.table.remove(bucketnum); + continue; + } - // Does this removal cause the bucket to go below the - // threshold? - if numreachable != MIN_BUCKET_REACHABILITY { - // No - continue; - } + // Does this removal cause the bucket to go below the + // threshold? + if numreachable != MIN_BUCKET_REACHABILITY { + // No + continue; + } - // This bucket is now unreachable. Get a spare bucket - if self.bridge_table.spares.is_empty() { - // Uh, oh. No spares available. Just delete any - // migrations leading to this bucket. - res = false; - self.trustup_migration_table - .table - .retain(|_, &mut v| v != *bucketnum); - self.blockage_migration_table - .table - .retain(|_, &mut v| v != *bucketnum); - } else { - // Get the first spare and remove it from the spares - // set. - let spare = *self.bridge_table.spares.iter().next().unwrap(); - self.bridge_table.spares.remove(&spare); - // Add a blockage migration from this bucket to the spare - self.blockage_migration_table - .table - .insert(*bucketnum, spare); - // Remove any trust upgrade migrations to this - // bucket - self.trustup_migration_table - .table - .retain(|_, &mut v| v != *bucketnum); - // Change any blockage migrations with this bucket - // as the destination to the spare - for (_, v) in self.blockage_migration_table.table.iter_mut() { - if *v == *bucketnum { - *v = spare; + // This bucket is now unreachable. Get a spare bucket + if self.bridge_table.spares.is_empty() { + // Uh, oh. No spares available. Just delete any + // migrations leading to this bucket. + res = false; + self.trustup_migration_table + .table + .retain(|_, &mut v| v != *bucketnum); + self.blockage_migration_table + .table + .retain(|_, &mut v| v != *bucketnum); + } else { + // Get the first spare and remove it from the spares + // set. + let spare = *self.bridge_table.spares.iter().next().unwrap(); + self.bridge_table.spares.remove(&spare); + // Add a blockage migration from this bucket to the spare + self.blockage_migration_table + .table + .insert(*bucketnum, spare); + // Remove any trust upgrade migrations to this + // bucket + self.trustup_migration_table + .table + .retain(|_, &mut v| v != *bucketnum); + // Change any blockage migrations with this bucket + // as the destination to the spare + for (_, v) in self.blockage_migration_table.table.iter_mut() { + if *v == *bucketnum { + *v = spare; + } } } } } + self.bridge_table.reachable.remove(bridge); } - self.bridge_table.reachable.remove(bridge); res } diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index b9c5d9e..a07fdde 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -598,6 +598,14 @@ fn test_redeem_invite() { println!("bob_cred = {:?}", bob_cred); } +#[test] +fn test_allocate_bridges() { + let mut th = TestHarness::new(); + // Check that any bridges in distributor_bridges are first added to unallocated bridges + // and finally are added as openinv_buckets + // TODO +} + #[test] fn test_update_bridge() { let mut th = TestHarness::new(); @@ -612,8 +620,7 @@ fn test_update_bridge() { ]; // Store first bridgeline to update later let bridgeline_to_update = bucket[0]; - // Created changed info for bridgeline to be updated to - let updated_info = bucket[0]; + // Create changed info for bridgeline to be updated to let infostr: String = format!( "type={} blocked_in={:?} protocol={} distribution={}", "obfs2 test bridge".to_string(), @@ -684,23 +691,169 @@ fn test_update_bridge() { #[test] fn test_bridge_replace() { - // TODO - let mut th = TestHarness::new(); - // Add new bridge to table with known values, - // check that I can find and update the values and that everything else stays the same + // Create 3 open invitation buckets and 3 spare buckets + let cases = vec!["available", "unallocated", "spare", "failed"]; + for case in cases { + let mut th: TestHarness; + if case != "failed" { + th = TestHarness::new(); + } else { + th = TestHarness::new_buckets(5, 0); + } + // Randomly select a bridge to replace + let table_size = th.ba.bridge_table.buckets.len(); + let num = rand::thread_rng().gen_range(0, table_size - 1); + let replaceable_bucket = th.ba.bridge_table.buckets.get(num).unwrap().clone(); + let replacement_bridge = &replaceable_bucket[0]; + assert!( + th.ba + .bridge_table + .reachable + .contains_key(replacement_bridge), + "Random bridge to replace not in reachable bridges" + ); + match case { + "available" => { + // Case one: available_bridge != null + let random_bridgeline = &BridgeLine::random(); + let unallocated_bridgeline = &BridgeLine::random(); + th.ba + .bridge_table + .unallocated_bridges + .push(*unallocated_bridgeline); + assert!( + th.ba + .bridge_table + .reachable + .get(random_bridgeline) + .is_none(), + "Random bridge already in table" + ); + assert!( + th.ba + .bridge_replace(replacement_bridge, Some(random_bridgeline), &mut th.bdb), + "Bridge was not replaced with available bridge" + ); + assert!( + th.ba + .bridge_table + .reachable + .get(random_bridgeline) + .is_some(), + "Replacement bridge not added to reachable bridges" + ); + assert!( + table_size == th.ba.bridge_table.buckets.len(), + "Number of buckets changed size" + ); + assert!( + th.ba.bridge_table.unallocated_bridges.len() == 1, + "Extra bridge added to unallocated bridges" + ); + println!("Successfully added passed bridgeline"); + } + // Case two: available_bridge == null and unallocated_bridges !=null + "unallocated" => { + let unallocated_bridgeline = &BridgeLine::random(); + th.ba + .bridge_table + .unallocated_bridges + .push(*unallocated_bridgeline); + assert!( + th.ba.bridge_table.unallocated_bridges.len() == 1, + "Not enough bridges in unallocated bridges" + ); + assert!( + th.ba + .bridge_table + .reachable + .get(unallocated_bridgeline) + .is_none(), + "Unallocated bridge already marked as reachable" + ); + assert!( + th.ba.bridge_replace(replacement_bridge, None, &mut th.bdb), + "Bridge was not replaced with available bridge" + ); + assert!( + th.ba + .bridge_table + .reachable + .get(unallocated_bridgeline) + .is_some(), + "Replacement bridge not added to reachable bridges" + ); + assert!( + table_size == th.ba.bridge_table.buckets.len(), + "Number of buckets changed size" + ); + assert!( + th.ba.bridge_table.unallocated_bridges.len() == 0, + "Allocated bridge still in unallocated bridges" + ); - // Create 3 bridges to test harness - let bucket = [ - BridgeLine::random(), - BridgeLine::random(), - BridgeLine::random(), - ]; + println!("Successfully added unallocated bridgeline"); + } + "spare" => { + // Case three: available_bridge == null and unallocated_bridges ==null + assert!( + th.ba.bridge_table.unallocated_bridges.len() == 0, + "Unallocated bridges should have a length of 0" + ); + assert!( + th.ba.bridge_replace(replacement_bridge, None, &mut th.bdb), + "Bridge was not replaced with available spare bridge" + ); + assert!( + th.ba + .bridge_table + .reachable + .get(replacement_bridge) + .is_none(), + "Replacement bridge still marked as reachable" + ); + assert!( + table_size == th.ba.bridge_table.buckets.len(), + "Number of buckets changed size" + ); + assert!( + th.ba.bridge_table.unallocated_bridges.len() == 2, + "Extra spare bridges not added to unallocated bridges" + ); -} - -#[test] -fn test_allocate_bridges() { - // TODO + println!("Successfully added unallocated bridgeline"); + } + "failed" => { + // Case four: available_bridge == None and unallocated_bridges == None and spare buckets == None + assert!( + th.ba.bridge_table.unallocated_bridges.len() == 0, + "Unallocated bridges should have a length of 0" + ); + assert!( + !th.ba.bridge_replace(replacement_bridge, None, &mut th.bdb), + "Bridge was somehow marked as replaced despite no replaceable bridges" + ); + assert!( + th.ba + .bridge_table + .reachable + .get(replacement_bridge) + .is_some(), + "Replacement bridge marked as unreachable despite not being replaced" + ); + assert!( + table_size == th.ba.bridge_table.buckets.len(), + "Number of buckets changed size" + ); + assert!( + th.ba.bridge_table.unallocated_bridges.len() == 0, + "Unallocated bridges changed size" + ); + println!("No bridges available to replace bridge so replacement gracefully failed"); + } + _ => {} + } + } } #[test] From 45bb5756df0cfc30053e8a9235780a2b63849972 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 15 May 2023 12:35:26 -0400 Subject: [PATCH 112/115] Minor fixes --- crates/lox-library/src/lib.rs | 11 +++++------ crates/lox-library/src/tests.rs | 8 ++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index a82b3da..925fac2 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -344,7 +344,7 @@ impl BridgeAuth { } while self.bridge_table.unallocated_bridges.len() >= MAX_BRIDGES_PER_BUCKET { let mut bucket = [BridgeLine::default(); MAX_BRIDGES_PER_BUCKET]; - for i in 0..MAX_BRIDGES_PER_BUCKET { + for i in 0..MAX_BRIDGES_PER_BUCKET { bucket[i] = self.bridge_table.unallocated_bridges.pop().unwrap(); } self.add_openinv_bridges(bucket, bdb); @@ -406,20 +406,19 @@ impl BridgeAuth { &mut self, bridge: &BridgeLine, available_bridge: Option<&BridgeLine>, - bdb: &mut BridgeDb, ) -> bool { let mut res: bool = false; let reachable_bridges = &self.bridge_table.reachable.clone(); if let Some(positions) = reachable_bridges.get(bridge) { - if available_bridge.is_some() { + if let Some(replacement) = available_bridge { for (bucketnum, offset) in positions.iter() { assert!(self.bridge_table.buckets[*bucketnum as usize][*offset] == *bridge); self.bridge_table.buckets[*bucketnum as usize][*offset] = - *available_bridge.unwrap(); + *replacement; // Remove the bridge from the reachable bridges and add new bridge self.bridge_table .reachable - .insert(*available_bridge.unwrap(), positions.clone()); + .insert(*replacement, positions.clone()); // Remove the bridge from the bucket self.bridge_table.reachable.remove(bridge); res = true @@ -442,7 +441,7 @@ impl BridgeAuth { // Indicate the removed bucket as a recyclable bucket self.bridge_table.recyclable.insert(spare); // Get the actual bridges from the spare bucket - let spare_bucket = self.bridge_table.buckets[spare as usize].clone(); + let spare_bucket = self.bridge_table.buckets[spare as usize]; let mut replacement: &BridgeLine = &BridgeLine::default(); // Make the first spare the replacement bridge, add the others to the set of // unallocated_bridges diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index a07fdde..8130b31 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -731,7 +731,7 @@ fn test_bridge_replace() { ); assert!( th.ba - .bridge_replace(replacement_bridge, Some(random_bridgeline), &mut th.bdb), + .bridge_replace(replacement_bridge, Some(random_bridgeline)), "Bridge was not replaced with available bridge" ); assert!( @@ -772,7 +772,7 @@ fn test_bridge_replace() { "Unallocated bridge already marked as reachable" ); assert!( - th.ba.bridge_replace(replacement_bridge, None, &mut th.bdb), + th.ba.bridge_replace(replacement_bridge, None), "Bridge was not replaced with available bridge" ); assert!( @@ -801,7 +801,7 @@ fn test_bridge_replace() { "Unallocated bridges should have a length of 0" ); assert!( - th.ba.bridge_replace(replacement_bridge, None, &mut th.bdb), + th.ba.bridge_replace(replacement_bridge, None), "Bridge was not replaced with available spare bridge" ); assert!( @@ -830,7 +830,7 @@ fn test_bridge_replace() { "Unallocated bridges should have a length of 0" ); assert!( - !th.ba.bridge_replace(replacement_bridge, None, &mut th.bdb), + !th.ba.bridge_replace(replacement_bridge, None), "Bridge was somehow marked as replaced despite no replaceable bridges" ); assert!( From 8d0f57062782eb5277da1ce12336040299679676 Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 15 May 2023 18:57:23 -0400 Subject: [PATCH 113/115] Adds test and fixes for allocate bridges --- crates/lox-library/src/lib.rs | 4 ++-- crates/lox-library/src/tests.rs | 24 +++++++++++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 925fac2..bc493c3 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -339,8 +339,8 @@ impl BridgeAuth { distributor_bridges: &mut Vec, bdb: &mut BridgeDb, ) { - while let Some(bridge) = distributor_bridges.iter().next_back() { - self.bridge_table.unallocated_bridges.push(*bridge) + while let Some(bridge) = distributor_bridges.pop() { + self.bridge_table.unallocated_bridges.push(bridge); } while self.bridge_table.unallocated_bridges.len() >= MAX_BRIDGES_PER_BUCKET { let mut bucket = [BridgeLine::default(); MAX_BRIDGES_PER_BUCKET]; diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 8130b31..5627d9a 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -601,9 +601,27 @@ fn test_redeem_invite() { #[test] fn test_allocate_bridges() { let mut th = TestHarness::new(); - // Check that any bridges in distributor_bridges are first added to unallocated bridges - // and finally are added as openinv_buckets - // TODO + let distributor_bridges: &mut Vec = &mut Vec::new(); + let table_size = th.ba.bridge_table.buckets.len(); + for _ in 0..3 { + distributor_bridges.push(BridgeLine::random()); + } + assert!(!distributor_bridges.is_empty(), "No BridgeLines in distributor_bridges"); + th.ba.allocate_bridges(distributor_bridges, &mut th.bdb); + assert!(distributor_bridges.is_empty(), "BridgeLines in distributor_bridges were not allocated"); + assert!(th.ba.bridge_table.buckets.len() > table_size, "Size of bridge table did not increase"); + let table_size = th.ba.bridge_table.buckets.len(); + for _ in 0..2 { + distributor_bridges.push(BridgeLine::random()); + th.ba.bridge_table.unallocated_bridges.push(BridgeLine::random()); + } + assert!(!th.ba.bridge_table.unallocated_bridges.is_empty(), "No BridgeLines in unallocated bridges"); + assert!(!distributor_bridges.is_empty(), "No BridgeLines in distributor_bridges"); + th.ba.allocate_bridges(distributor_bridges, &mut th.bdb); + assert!(th.ba.bridge_table.unallocated_bridges.len() == 1, "Incorrect number of bridges remain unallocated"); + assert!(distributor_bridges.is_empty(), "BridgeLines in distributor_bridges were not allocated"); + assert!(th.ba.bridge_table.buckets.len() > table_size, "Size of bridge table did not increase"); + } #[test] From a9d5f318705ab427d97c5bbf02dd8d4ed42df2aa Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 15 May 2023 23:33:23 +0000 Subject: [PATCH 114/115] Add test pipeline --- crates/lox-library/.gitlab-ci.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 crates/lox-library/.gitlab-ci.yml diff --git a/crates/lox-library/.gitlab-ci.yml b/crates/lox-library/.gitlab-ci.yml new file mode 100644 index 0000000..b538127 --- /dev/null +++ b/crates/lox-library/.gitlab-ci.yml @@ -0,0 +1,12 @@ +image: "rust:latest" + +test:cargo: + script: + - rustc --version && cargo --version # Print version info for debugging + - cargo test --workspace --verbose + +test:lox-unit: + script: + - cargo test -- release + artifacts: + when: always From 607e1a425d89b66736720b1f5ae660e500e26eff Mon Sep 17 00:00:00 2001 From: onyinyang Date: Mon, 15 May 2023 19:55:52 -0400 Subject: [PATCH 115/115] Remove performance statistics tests for pipeline --- crates/lox-library/Dockerfile | 13 - .../lox-library/Parsing-results/blockages.py | 60 - .../Parsing-results/check_blockages.py | 110 -- .../Parsing-results/make_steady.py | 79 -- .../Parsing-results/make_tables.py | 68 -- .../lox-library/Parsing-results/parse_data.sh | 14 - .../Parsing-results/performance.py | 63 - .../lox-library/Parsing-results/pets_plots.py | 62 - .../lox-library/Parsing-results/raw_to_csv.py | 176 --- .../Parsing-results/requirements.txt | 15 - .../Parsing-results/trust_promo.py | 86 -- .../Parsing-results/trust_promo_plot.py | 74 -- crates/lox-library/README.md | 60 +- crates/lox-library/build-lox.sh | 2 - crates/lox-library/run-lox.sh | 2 - crates/lox-library/run_tests_fast.sh | 29 - crates/lox-library/src/tests.rs | 1050 +---------------- 17 files changed, 2 insertions(+), 1961 deletions(-) delete mode 100644 crates/lox-library/Dockerfile delete mode 100644 crates/lox-library/Parsing-results/blockages.py delete mode 100644 crates/lox-library/Parsing-results/check_blockages.py delete mode 100644 crates/lox-library/Parsing-results/make_steady.py delete mode 100644 crates/lox-library/Parsing-results/make_tables.py delete mode 100755 crates/lox-library/Parsing-results/parse_data.sh delete mode 100644 crates/lox-library/Parsing-results/performance.py delete mode 100644 crates/lox-library/Parsing-results/pets_plots.py delete mode 100644 crates/lox-library/Parsing-results/raw_to_csv.py delete mode 100644 crates/lox-library/Parsing-results/requirements.txt delete mode 100644 crates/lox-library/Parsing-results/trust_promo.py delete mode 100644 crates/lox-library/Parsing-results/trust_promo_plot.py delete mode 100755 crates/lox-library/build-lox.sh delete mode 100755 crates/lox-library/run-lox.sh delete mode 100755 crates/lox-library/run_tests_fast.sh diff --git a/crates/lox-library/Dockerfile b/crates/lox-library/Dockerfile deleted file mode 100644 index 954c37f..0000000 --- a/crates/lox-library/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM rust:1.56.0 -WORKDIR /home/lox -ADD src/ ./src/ -ADD Cargo.toml Cargo.toml -ADD tests/ ./tests/ -ADD run_tests_fast.sh . -ADD Parsing-results ./Parsing-results -ADD README.md README.md -RUN apt update -y -RUN apt install -y python3 python3-pip -RUN pip3 install -r Parsing-results/requirements.txt -RUN cargo build --release -ENV SHELL=/bin/bash diff --git a/crates/lox-library/Parsing-results/blockages.py b/crates/lox-library/Parsing-results/blockages.py deleted file mode 100644 index 6da60c4..0000000 --- a/crates/lox-library/Parsing-results/blockages.py +++ /dev/null @@ -1,60 +0,0 @@ -import pandas as pd -import matplotlib.pyplot as plt -from matplotlib.lines import Line2D - -fig, (axs, axs1) = plt.subplots(2, 4, figsize=(24, 12)) -fig.suptitle("Checking for Blockage and Migration to new Bridges for" + - " Percentage of Bridges Blocked") -columns = ["Percent", "RequestT", "Rtstdev", "ResponseS", "ResponseT", - "ReTstdev", "ResponseHT", "RHTstdev"] -df = pd.read_csv("check_blockage.csv", usecols=columns) -df1 = pd.read_csv("migration.csv", usecols=columns) -fig.supxlabel('Blocked Bridges (%)') -axs[0].set_ylabel('Request Time (ms)') -axs[0].set_ylim([0,70]) -l1 = axs[0].plot(df.Percent, df.RequestT, color='#CC4F1B', - label='Request Time for Percentage of Bridges Blocked') -axs[0].fill_between(df.Percent, df.RequestT-df.Rtstdev, df.RequestT+df.Rtstdev, - alpha=0.5, edgecolor='#CC4F1B', facecolor='#FF9848') -axs1[0].set_ylabel('Request Time (ms)') -axs1[0].set_ylim([0,70]) -axs1[0].plot(df1.Percent, df1.RequestT, color='#1B2ACC', - label='Request Time for Percentage of Bridges Blocked') -axs1[0].fill_between(df1.Percent, df1.RequestT-df1.Rtstdev, - df1.RequestT+df1.Rtstdev, alpha=0.2, edgecolor='#1B2ACC', - facecolor='#089FFF') -axs[1].set_ylabel('Response Time (ms)') -axs[1].plot(df.Percent, df.ResponseT, color='#CC4F1B', - label='Response Time for Percentage of Bridges Blocked') -axs[1].fill_between(df.Percent, df.ResponseT-df.ReTstdev, - df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#CC4F1B', - facecolor='#FF9848') -axs1[1].set_ylabel('Response Time (ms)') -axs1[1].set_ylim([0,70]) -axs1[1].plot(df1.Percent, df1.ResponseT, color='#1B2ACC', - label='Response Time for Percentage of Bridges Blocked') -axs1[1].fill_between(df1.Percent, df1.ResponseT-df1.ReTstdev, - df1.ResponseT+df1.ReTstdev, alpha=0.2, edgecolor='#1B2ACC', - facecolor='#089FFF') -axs[2].set_ylabel('Response Size (ms)') -axs[2].plot(df.Percent, df.ResponseS, color='#CC4F1B', - label='Response Size for Percentage of Bridges Blocked') -axs1[2].set_ylabel('Response Size (ms)') -axs1[2].plot(df1.Percent, df1.ResponseS, color='#1B2ACC', - label='Response Size for Percentage of Bridges Blocked') -axs[3].set_ylabel('Response Handling Time (ms)') -axs[3].plot(df.Percent, df.ResponseHT, color='#CC4F1B', - label='Response Handling Time for Percentage of Bridges Blocked') -axs[3].fill_between(df.Percent, df.ResponseHT-df.RHTstdev, - df.ResponseHT+df.RHTstdev, alpha=0.5, edgecolor='#CC4F1B', - facecolor='#FF9848') -axs1[3].set_ylabel('Response Handling Time (ms)') -axs1[3].set_ylim([0,70]) -axs1[3].plot(df1.Percent, df1.ResponseHT, color='#1B2ACC', - label='Response Handling Time for Percentage of Bridges Blocked') -axs1[3].fill_between(df1.Percent, df1.ResponseHT-df1.RHTstdev, - df1.ResponseHT+df1.RHTstdev, alpha=0.2, edgecolor='#1B2ACC', - facecolor='#089FFF') -legend_elements = [Line2D([0], [0], color='#CC4F1B', label="Check Blockage Protocol"), Line2D([0], [0], color='#1B2ACC', label="Blockage Migration Protocol")] -fig.legend(handles=legend_elements, loc='lower right') -fig.savefig("Performance.pdf") diff --git a/crates/lox-library/Parsing-results/check_blockages.py b/crates/lox-library/Parsing-results/check_blockages.py deleted file mode 100644 index 4e820c6..0000000 --- a/crates/lox-library/Parsing-results/check_blockages.py +++ /dev/null @@ -1,110 +0,0 @@ -import sys -import pandas as pd -import matplotlib -import matplotlib.pyplot as plt -from matplotlib.lines import Line2D - - -def main(): - - fig, axs = plt.subplots(1, 3, figsize=(24, 7)) - columns = ["Percent","Bridges", "RequestT", "Rtstdev", "ResponseS", "ResponseT", - "ReTstdev", "ResponseHT", "RHTstdev"] - df = pd.read_csv("standard_check"+".csv", usecols=columns) - df.sort_values(["Percent"], axis=0,ascending=[False], inplace=True) - bridges = df.Bridges*2*3 - fig.supxlabel('Blocked Bridges (%)', size=30) - axs[0].set_ylabel('Response Time (ms)', size=25) - axs[0].tick_params(axis='x', labelsize=15) - axs[0].tick_params(axis='y', labelsize=15) -# axs[0].set_xticklabels('Blocked Bridges (%)',fontsize=10) - axs[0].plot(df.Percent, df.ResponseT, color='#CC4F1B', - label='Response Time for Percentage of Bridges Blocked') - axs[0].fill_between(df.Percent, df.ResponseT-df.ReTstdev, - df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#CC4F1B', - facecolor='#FF9848') - axs[1].set_ylabel('Response Size (bytes)', size=25) - axs[1].tick_params(axis='x', labelsize=15) - axs[1].tick_params(axis='y', labelsize=15) - axs[1].plot(df.Percent, df.ResponseS, color='#CC4F1B', - label='Response Size for Percentage of Bridges Blocked') - axs[2].set_ylabel('Response Handling Time (ms)', size=25) - axs[2].tick_params(axis='x', labelsize=15) - axs[2].tick_params(axis='y', labelsize=15) - axs[2].plot(df.Percent, df.ResponseHT, color='#CC4F1B', - label='Response Handling Time for Percentage of Bridges Blocked') - axs[2].fill_between(df.Percent, df.ResponseHT-df.RHTstdev, - df.ResponseHT+df.RHTstdev, alpha=0.5, edgecolor='#CC4F1B', - facecolor='#FF9848') - fig. tight_layout(pad=1) - fig.savefig("StandardCheck.pdf") - plt.close('all') - - for n in range(5,105,5): - fig, axs = plt.subplots(1, 3, figsize=(24, 7)) - columns = ["Percent","Bridges", "RequestT", "Rtstdev", "ResponseS", "ResponseT", - "ReTstdev", "ResponseHT", "RHTstdev"] - df = pd.read_csv("checkblockage"+str(n)+".csv", usecols=columns) - bridges = df.Bridges*2*3 - fig.supxlabel('Total Size of Bridge Pool ('+str(n)+'% Bridges Blocked)',size=30) - axs[0].set_ylabel('Response Time (ms)', size=25) - axs[0].tick_params(axis='x', labelsize=15) - axs[0].tick_params(axis='y', labelsize=15) - axs[0].plot(bridges, df.ResponseT, color='#740202', - label='Response Time for Percentage of Bridges Blocked') - axs[0].fill_between(bridges, df.ResponseT-df.ReTstdev, - df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#740202', - facecolor='#E75252') - axs[1].set_ylabel('Response Size (bytes)', size=25) - axs[1].tick_params(axis='x', labelsize=15) - axs[1].tick_params(axis='y', labelsize=15) - axs[1].plot(bridges, df.ResponseS, color='#740202', - label='Response Size for Percentage of Bridges Blocked') - axs[2].set_ylabel('Response Handling Time (ms)', size=25) - axs[2].tick_params(axis='x', labelsize=15) - axs[2].tick_params(axis='y', labelsize=15) - axs[2].plot(bridges, df.ResponseHT, color='#740202', - label='Response Handling Time for Percentage of Bridges Blocked') - axs[2].fill_between(bridges, df.ResponseHT-df.RHTstdev, - df.ResponseHT+df.RHTstdev, alpha=0.5, edgecolor='#740202', - facecolor='#E75252') - fig. tight_layout(pad=1) - fig.savefig("PerformanceVaried"+str(n)+".pdf") - print("\nDone PerformanceVaried"+str(n)+" Plot.\nOutput to: PerformanceVaried"+str(n)+".pdf") - plt.close('all') - - -def set_plot_options(): - options = { - 'font.size': 12, - 'figure.figsize': (4,2), - 'figure.dpi': 100.0, - 'figure.subplot.left': 0.20, - 'figure.subplot.right': 0.97, - 'figure.subplot.bottom': 0.20, - 'figure.subplot.top': 0.90, - 'grid.color': '0.1', - 'grid.linestyle': ':', - #'grid.linewidth': 0.5, - 'axes.grid' : True, - #'axes.grid.axis' : 'y', - #'axes.axisbelow': True, - 'axes.titlesize' : 25, - 'axes.labelsize' : 25, - 'axes.formatter.limits': (-4,4), - 'xtick.labelsize' : 30,#get_tick_font_size_10(), - 'ytick.labelsize' : 30,#get_tick_font_size_10(), - 'lines.linewidth' : 2.0, - 'lines.markeredgewidth' : 0.5, - 'lines.markersize' : 15, - } - - for option_key in options: - matplotlib.rcParams[option_key] = options[option_key] - if 'figure.max_num_figures' in matplotlib.rcParams: - matplotlib.rcParams['figure.max_num_figures'] = 100 - if 'figure.max_open_warning' in matplotlib.rcParams: - matplotlib.rcParams['figure.max_open_warning'] = 100 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/crates/lox-library/Parsing-results/make_steady.py b/crates/lox-library/Parsing-results/make_steady.py deleted file mode 100644 index 674dfee..0000000 --- a/crates/lox-library/Parsing-results/make_steady.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python - -import sys -import json -import lzma -import numpy as np - -import matplotlib -import matplotlib.pyplot as pyplot -import matplotlib.colors as mcolors - - -def main(): - set_plot_options() - buckets = [600, 1200, 1800, 2400, 3000] - n = 1000000 - ft = [] - - pyplot.figure() - for b in buckets: - delta = np.arange(1/10,1,.01) - x = [] - for d in delta: - p = n*(1.61 + (14.71/d+23.725/d**2)/b) / 86400000 - x.append(p) - ft.append(x) - - - pyplot.plot(delta, ft[0], label='600 Buckets') - pyplot.plot(delta, ft[1], linestyle='dotted', label='1200 Buckets') - pyplot.plot(delta, ft[2], linestyle='dashed', label='1800 Buckets') - pyplot.plot(delta, ft[3], linestyle='dashdot', label='2400 Buckets') - pyplot.plot(delta, ft[4], label='3000 Buckets') - pyplot.ylim(bottom=0) - - pyplot.xlabel(r'$\Delta$') - pyplot.ylabel("Cores / Million Users") -# pyplot.title("Average Number of Bridge Users for 1 Month Old Bridges November 2021") - - - pyplot.legend(loc="upper right") - pyplot.tight_layout(pad=1) - pyplot.savefig("core-users.pdf") - -def set_plot_options(): - options = { - #'backend': 'PDF', - 'font.size': 18, - 'figure.figsize': (7,4), - 'figure.dpi': 100.0, - 'axes.grid' : True, - 'axes.xmargin' : 0, - 'axes.grid.axis' : 'y', - 'axes.axisbelow': True, - 'axes.titlesize' : 'medium', - 'axes.labelsize' : 'large', - 'axes.formatter.limits': (-6,6), - 'xtick.labelsize' : 18,#get_tick_font_size_10(), - 'ytick.labelsize' : 18, - 'lines.linewidth' : 2.0, - 'lines.markersize' : 10, - # turn on the following to embedd fonts; requires latex - 'ps.useafm' : True, - 'pdf.use14corefonts' : True, - 'text.usetex' : False, - } - - for option_key in options: - matplotlib.rcParams[option_key] = options[option_key] - - if 'figure.max_num_figures' in matplotlib.rcParams: - matplotlib.rcParams['figure.max_num_figures'] = 100 - if 'figure.max_open_warning' in matplotlib.rcParams: - matplotlib.rcParams['figure.max_open_warning'] = 100 - if 'legend.ncol' in matplotlib.rcParams: - matplotlib.rcParams['legend.ncol'] = 100 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/crates/lox-library/Parsing-results/make_tables.py b/crates/lox-library/Parsing-results/make_tables.py deleted file mode 100644 index 61a0eea..0000000 --- a/crates/lox-library/Parsing-results/make_tables.py +++ /dev/null @@ -1,68 +0,0 @@ -import csv -import sys -import pandas as pd -import numpy as np - - -def main(): - perf = open("performance_stats"+".csv", "w", newline='') - protocols=["Open Invitation", "Trust Promotion(0->1)", - "Trust Migration (0->1)", "Level Up (1->4)", "Issue Invitation", - "Redeem Invitation", "Check Blockage 5%", "Check Blockage 50%", "Check Blockage 100%", "Blockage Migration"] - files = ["trust_levels.csv", "trust_promo.csv", "trust_mig.csv", "level2.csv", - "invitations.csv", "redeem_invites.csv","check_blockage5.csv", - "check_blockage50.csv","check_blockage100.csv","blockage_migration50.csv"] - csv_cols = ["RequestS", "RequestT","Rtstdev","ResponseS","ResponseT", - "ReTstdev", "ResponseHT", "RHTstdev"] - perf_columns = ["Protocol","Request Size", "Request Time", "sigma", - "Response Size","Response Time", "sigma", - "Response Handling Time", "sigma"] - worst_resp = 0 - perfwriter = csv.writer(perf, delimiter=',') - perfwriter.writerow(perf_columns) - - for i, protocol in enumerate(protocols): - columns = ["Percent","Bridges", "RequestS", "Rsstdev", "RequestT", - "Rtstdev", "ResponseS","Restdev","ResponseT", - "ReTstdev", "ResponseHT", "RHTstdev"] - df = pd.read_csv(files[i], usecols=columns) - perf_in = [] - - perf_in.append(protocol) - for item in csv_cols: - row = df[item].loc[df['Bridges']==900].values - if "stdev" in item: - rounded = np.round(row[0], decimals=1) - else: - rounded = np.round(row[0], decimals=3) - perf_in.append(rounded) - rounded = np.round(row[0], decimals=1) - if item == "RequestT": - req = np.round(rounded, decimals=1) - elif item == "ResponseT": - resp_sec = np.round(1000/rounded, decimals=1) - resp_core = resp_sec/(1/(60*60*24)) - if rounded > worst_resp: - worst_resp = rounded - - - perfwriter.writerow(perf_in) - - for i, protocol in enumerate(protocols): - columns = ["Percent","Bridges", "RequestS", "Rsstdev", "RequestT", - "Rtstdev", "ResponseS","Restdev","ResponseT", - "ReTstdev", "ResponseHT", "RHTstdev"] - df = pd.read_csv(files[i], usecols=columns) - row = df['ResponseT'].loc[df['Bridges']==900].values - rounded = np.round(row[0], decimals=3) - resp_sec = np.round(1000/rounded, decimals=3) - resp_core = int(resp_sec/(1/(60*60*24))) - if worst_resp > rounded: - secs = int(worst_resp/1000) - - perf.close() - print("\nDone Tables.\nTable data output to: performance_stats.csv,\n") - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/crates/lox-library/Parsing-results/parse_data.sh b/crates/lox-library/Parsing-results/parse_data.sh deleted file mode 100755 index f8d30fb..0000000 --- a/crates/lox-library/Parsing-results/parse_data.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -# Parse results from Lox stat tests -echo 'Parse raw output to csv' - -python3 raw_to_csv.py - -echo 'Make plots for data' - -#python3 check_blockages.py -python3 pets_plots.py -#python3 trust_promo_plot.py -python3 make_tables.py -python3 make_steady.py diff --git a/crates/lox-library/Parsing-results/performance.py b/crates/lox-library/Parsing-results/performance.py deleted file mode 100644 index 0a3b58f..0000000 --- a/crates/lox-library/Parsing-results/performance.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python - -import sys -import pandas as pd -import matplotlib -import matplotlib.pyplot as plt -from matplotlib.lines import Line2D - - -def main(): - set_plot_options() - fig, axs = plt.subplots(1) - columns = ["Percent","Bridges", "RequestT", "Rtstdev", "ResponseS", "ResponseT", - "ReTstdev", "ResponseHT", "RHTstdev"] - df = pd.read_csv("standard_check"+".csv", usecols=columns) - df.sort_values(["Percent"], axis=0,ascending=[False], inplace=True) - bridges = df.Bridges*2*3 - axs.set_xlabel('Blocked Bridges (%)') - axs.set_ylabel('Response Time (ms)') - axs.plot(df.Percent, df.ResponseT, color='#CC4F1B', - label='Response Time for Percentage of Bridges Blocked') - axs.set_ylim(bottom=0) - axs.fill_between(df.Percent, df.ResponseT-df.ReTstdev, - df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#CC4F1B', - facecolor='#FF9848') - fig. tight_layout(pad=1) - fig.savefig("StandardCheck.pdf") - -def set_plot_options(): - options = { - #'backend': 'PDF', - 'font.size': 18, - 'figure.figsize': (7,3.5), - 'figure.dpi': 100.0, - 'axes.grid' : True, - 'axes.xmargin' : 0, - 'axes.grid.axis' : 'y', - 'axes.axisbelow': True, - 'axes.titlesize' : 'medium', - 'axes.labelsize' : 'large', - 'axes.formatter.limits': (-6,6), - 'xtick.labelsize' : 18,#get_tick_font_size_10(), - 'ytick.labelsize' : 18, - 'lines.linewidth' : 2.0, - 'lines.markersize' : 10, - # turn on the following to embedd fonts; requires latex - 'ps.useafm' : True, - 'pdf.use14corefonts' : True, - 'text.usetex' : False, - } - - for option_key in options: - matplotlib.rcParams[option_key] = options[option_key] - - if 'figure.max_num_figures' in matplotlib.rcParams: - matplotlib.rcParams['figure.max_num_figures'] = 100 - if 'figure.max_open_warning' in matplotlib.rcParams: - matplotlib.rcParams['figure.max_open_warning'] = 100 - if 'legend.ncol' in matplotlib.rcParams: - matplotlib.rcParams['legend.ncol'] = 100 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/crates/lox-library/Parsing-results/pets_plots.py b/crates/lox-library/Parsing-results/pets_plots.py deleted file mode 100644 index df8557f..0000000 --- a/crates/lox-library/Parsing-results/pets_plots.py +++ /dev/null @@ -1,62 +0,0 @@ -import sys -import pandas as pd -import matplotlib -import matplotlib.pyplot as plt -from matplotlib.lines import Line2D - - -def main(): - - plt.figure(figsize=(9, 5)) - columns = ["Percent","Bridges", "RequestT", "Rtstdev", "ResponseS", "ResponseT", - "ReTstdev", "ResponseHT", "RHTstdev"] - df = pd.read_csv("standard_check"+".csv", usecols=columns) - df.sort_values(["Percent"], axis=0,ascending=[False], inplace=True) - bridges = df.Bridges*2*3 - plt.xlabel('Blocked Bridges (%)', size=20) - plt.ylabel('Response Time (ms)', size=20) - plt.tick_params(axis='x', labelsize=15) - plt.tick_params(axis='y', labelsize=15) - plt.plot(df.Percent, df.ResponseT, color='#CC4F1B', - label='Response Time for Percentage of Bridges Blocked') - plt.fill_between(df.Percent, df.ResponseT-df.ReTstdev, - df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#CC4F1B', - facecolor='#FF9848') - plt.tight_layout(pad=1) - plt.savefig("Blockage-response-time.pdf") - plt.close('all') - -def set_plot_options(): - options = { - 'font.size': 12, - 'figure.figsize': (10,2), - 'figure.dpi': 100.0, - 'figure.subplot.left': 0.20, - 'figure.subplot.right': 0.97, - 'figure.subplot.bottom': 0.20, - 'figure.subplot.top': 0.90, - 'grid.color': '0.1', - 'grid.linestyle': ':', - #'grid.linewidth': 0.5, - 'axes.grid' : True, - #'axes.grid.axis' : 'y', - #'axes.axisbelow': True, - 'axes.titlesize' : 25, - 'axes.labelsize' : 25, - 'axes.formatter.limits': (-4,4), - 'xtick.labelsize' : 30,#get_tick_font_size_10(), - 'ytick.labelsize' : 30,#get_tick_font_size_10(), - 'lines.linewidth' : 2.0, - 'lines.markeredgewidth' : 0.5, - 'lines.markersize' : 15, - } - - for option_key in options: - matplotlib.rcParams[option_key] = options[option_key] - if 'figure.max_num_figures' in matplotlib.rcParams: - matplotlib.rcParams['figure.max_num_figures'] = 100 - if 'figure.max_open_warning' in matplotlib.rcParams: - matplotlib.rcParams['figure.max_open_warning'] = 100 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/crates/lox-library/Parsing-results/raw_to_csv.py b/crates/lox-library/Parsing-results/raw_to_csv.py deleted file mode 100644 index 090cd8e..0000000 --- a/crates/lox-library/Parsing-results/raw_to_csv.py +++ /dev/null @@ -1,176 +0,0 @@ -from pathlib import Path - -standard_check_file = open("standard_check"+".csv", "w") -standard_check_file.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") - -for p in Path('.').glob('*.log'): - print(f"Parsing: {p.name.strip('.log')}\n") - with p.open() as log_file: - test_file = open(p.name.strip('.log')+".csv", "w") - test_file.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") - bridges = 0 - c=False - red = 0 - check = 0 - level = 0 - protocol = 0 - num = 0 - req_size = 0 - req_size_std = 0 - req_time = 0 - req_time_std = 0 - resp_size = 0 - resp_size_std = 0 - resp_time = 0 - resp_time_std = 0 - resp_handle_time = 0 - resp_handle_std = 0 - endline = 0 - - # Loop over the remaining lines in the file - for line in log_file: - if "***START" in line: - bridges = line.split()[1].split("*")[0] - if "CHECK-BLOCKAGE" in line: - protocol = 1 - num = line.split("-")[6].strip('-') - if int(bridges) == 900: - check =1 - if not c: - check_b = open("check_blockage"+str(num)+".csv", "w") - check_b.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") - c=True - elif "BLOCKAGE-MIGRATION" in line: - protocol = 2 - num = line.split("-")[6].strip('-') - elif "REDEEM" in line: - protocol = 3 - if not red: - redeem = open("redeem_invites.csv", "w") - redeem.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") - red = 1 - elif "ISSUE" in line: - protocol = 4 - elif "OPEN" in line: - protocol = 5 - elif "TRUST-PROMOTION" in line: - protocol = 6 - if not level: - trust_promo = open("trust_promo.csv", "w") - trust_promo.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") - elif "TRUST-MIGRATION" in line: - protocol = 7 - if not level: - mig_file = open("trust_mig.csv", "w") - mig_file.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") - elif "LEVEL-UP-2" in line: - protocol = 8 - if not level: - level_file = open("level2.csv", "w") - level_file.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") - elif "LEVEL-UP-3" in line: - protocol = 9 - if not level: - level_file_t = open("level3.csv", "w") - level_file_t.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") - elif "LEVEL-UP-4" in line: - protocol = 10 - if not level: - level_file_f = open("level4.csv", "w") - level_file_f.write("Percent,Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") - level = 1 - elif protocol: - value = line.split(" = ") - if value[0].startswith("Average"): - if "request" in value[0]: - if "size" in value[0]: - raw_size = value[1].split(" ") - req_size = raw_size[0] - else: - if "µ" in value[1]: - micro_sec = value[1].split("µ") - raw_size = float(micro_sec[0])*0.001 - elif "m" not in value[1]: - sec = value[1][:-3] - raw_size = float(sec)*1000 - else: - raw_size = value[1][:-3] - req_time = raw_size - else: - if "size" in value[0]: - raw_size = value[1].split(" ") - resp_size = raw_size[0] - else: - if "µ" in value[1]: - micro_sec = value[1].split("µ") - raw_size = float(micro_sec[0])*0.001 - elif "m" not in value[1]: - sec = value[1][:-3] - raw_size = float(sec)*1000 - else: - raw_size = value[1][:-3] - if "handling" in value[0]: - resp_handle_time = raw_size - else: - resp_time = raw_size - elif value[0].startswith("Request"): - if "size" in value[0]: - raw_size = value[1].split(" ") - req_size_std = raw_size[0] - else: - if "µ" in value[1]: - micro_sec = value[1].split("µ") - to_sec = float(micro_sec[0])*0.001 - else: - to_sec = value[1][:-3] - req_time_std = to_sec - elif value[0].startswith("Response"): - if "size" in value[0]: - raw_size = value[1].split(" ") - resp_size_std = raw_size[0] - else: - if "µ" in value[1]: - micro_sec = value[1].split("µ") - to_sec = float(micro_sec[0])*0.001 - else: - to_sec = value[1][:-3] - if "handling" in value[0]: - resp_handle_time_std = to_sec - endline = 1 - else: - resp_time_std = to_sec - - if endline == 1: - if check == 1: - standard_check_file.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") - check = 0 - if protocol == 1: - check_b.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") - elif protocol == 3: - redeem.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") - elif protocol<6: - test_file.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") - else: - if protocol == 6: - trust_promo.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") - if protocol == 7: - mig_file.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") - if protocol == 8: - level_file.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") - elif protocol == 9: - level_file_t.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") - elif protocol == 10: - level_file_f.write(str(num) + "," + str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") - endline = 0 - protocol = 0 - if level: - level_file.close() - level_file_t.close() - level_file_f.close() - trust_promo.close() - mig_file.close() - if red: - redeem.close() - test_file.close() -standard_check_file.close() -print("Done.") diff --git a/crates/lox-library/Parsing-results/requirements.txt b/crates/lox-library/Parsing-results/requirements.txt deleted file mode 100644 index 77e0143..0000000 --- a/crates/lox-library/Parsing-results/requirements.txt +++ /dev/null @@ -1,15 +0,0 @@ -contourpy==1.0.5 -cycler==0.11.0 -fonttools==4.37.4 -kiwisolver==1.4.4 -matplotlib==3.6.1 -mercurial==5.6.1 -numpy==1.23.4 -packaging==21.3 -pandas==1.5.0 -Pillow==9.2.0 -pyparsing==3.0.9 -python-dateutil==2.8.2 -pytz==2022.4 -six==1.16.0 - diff --git a/crates/lox-library/Parsing-results/trust_promo.py b/crates/lox-library/Parsing-results/trust_promo.py deleted file mode 100644 index c8fb0ae..0000000 --- a/crates/lox-library/Parsing-results/trust_promo.py +++ /dev/null @@ -1,86 +0,0 @@ -log_file = open("trust_levels.log", "r").readlines() -trust_promo_file = open("trust_promo"+".csv", "w") -trust_promo_file.write("Bridges,RequestS,Rsstdev,RequestT,Rtstdev,ResponseS,Restdev,ResponseT,ReTstdev,ResponseHT,RHTstdev\n") - - -bridges = 0 -promo = 0 -req_size = 0 -req_size_std = 0 -req_time = 0 -req_time_std = 0 -resp_size = 0 -resp_size_std = 0 -resp_time = 0 -resp_time_std = 0 -resp_handle_time = 0 -resp_handle_std = 0 -endline = 0 - -# Loop over the remaining lines in the file -for line in log_file: - if "***START" in line: - bridges = line.split()[1].split("*")[0] - elif "TRUST-PROMOTION" in line: - promo = 1 - elif promo: - value = line.split(" = ") - if value[0].startswith("Average"): - if "request" in value[0]: - if "size" in value[0]: - raw_size = value[1].split(" ") - req_size = raw_size[0] - else: - raw_size = value[1] - req_time = raw_size[:-3] - else: - if "size" in value[0]: - raw_size = value[1].split(" ") - resp_size = raw_size[0] - else: - raw_size = value[1] - if "handling" in value[0]: - resp_handle_time = raw_size[:-3] - elif (value[1][-3]) != "m": - sec = value[1][:-3] - resp_time = float(sec)*1000 - else: - resp_time = raw_size[:-3] - elif value[0].startswith("Request"): - if "size" in value[0]: - raw_size = value[1].split(" ") - req_size_std = raw_size[0] - else: - if "µ" in value[1]: - micro_sec = value[1].split("µ") - to_sec = float(micro_sec[0])*0.001 - else: - to_sec = value[1][:-3] - req_time_std = to_sec - - elif value[0].startswith("Response"): - if "size" in value[0]: - raw_size = value[1].split(" ") - resp_size_std = raw_size[0] - elif "bytes" in value[1]: - continue - else: - if "µ" in value[1]: - micro_sec = value[1].split("µ") - to_sec = float(micro_sec[0])*0.001 - else: - to_sec = value[1][:-3] - if "handling" in value[0]: - resp_handle_time_std = to_sec - endline = 1 - else: - resp_time_std = to_sec - - if endline == 1: - if promo == 1: - trust_promo_file.write(str(bridges)+"," + str(req_size) + "," + str(req_size_std) + "," + str(req_time) + "," + str(req_time_std) + "," + str(resp_size) + "," + str(resp_size_std) + "," + str(resp_time) + "," + str(resp_time_std) + "," + str(resp_handle_time) + "," + str(resp_handle_time_std) + "\n") - promo = 0 - endline = 0 - -trust_promo_file.close() -print("Done.") diff --git a/crates/lox-library/Parsing-results/trust_promo_plot.py b/crates/lox-library/Parsing-results/trust_promo_plot.py deleted file mode 100644 index 7c1eaea..0000000 --- a/crates/lox-library/Parsing-results/trust_promo_plot.py +++ /dev/null @@ -1,74 +0,0 @@ -import sys -import pandas as pd -import matplotlib -import matplotlib.pyplot as plt -from matplotlib.lines import Line2D - - -def main(): - - fig, axs = plt.subplots(1, 3, figsize=(24, 7)) - columns = ["Bridges", "RequestT", "Rtstdev", "ResponseS", "ResponseT", - "ReTstdev", "ResponseHT", "RHTstdev"] - df = pd.read_csv("trust_promo"+".csv", usecols=columns) - bridges = df.Bridges*2*3 - fig.supxlabel('Total Size of Bridge Pool',size=30) - axs[0].set_ylabel('Response Time (ms)', size=25) - axs[0].tick_params(axis='x', labelsize=15) - axs[0].tick_params(axis='y', labelsize=15) - axs[0].plot(bridges, df.ResponseT, color='#29135F', - label='Response Time for Trust Promotion') - axs[0].fill_between(bridges, df.ResponseT-df.ReTstdev, - df.ResponseT+df.ReTstdev, alpha=0.5, edgecolor='#29135F', - facecolor='#8967E2') - axs[1].set_ylabel('Response Size (bytes)', size=25) - axs[1].tick_params(axis='x', labelsize=15) - axs[1].tick_params(axis='y', labelsize=15) - axs[1].plot(bridges, df.ResponseS, color='#29135F', - label='Response Size for Trust Promotion') - axs[2].set_ylabel('Response Handling Time (ms)', size=25) - axs[2].tick_params(axis='x', labelsize=15) - axs[2].tick_params(axis='y', labelsize=15) - axs[2].plot(bridges, df.ResponseHT, color='#29135F', - label='Response Handling Time for Trust Promotion') - axs[2].fill_between(bridges, df.ResponseHT-df.RHTstdev, - df.ResponseHT+df.RHTstdev, alpha=0.5, edgecolor='#29135F', - facecolor='#8967E2') - fig. tight_layout(pad=1) - fig.savefig("TrustPromotion.pdf") - print("\nDone Trust Promotion Plot.\nOutput to: TrustPromotion.pdf") - -def set_plot_options(): - options = { - 'font.size': 12, - 'figure.figsize': (4,2), - 'figure.dpi': 100.0, - 'figure.subplot.left': 0.20, - 'figure.subplot.right': 0.97, - 'figure.subplot.bottom': 0.20, - 'figure.subplot.top': 0.90, - 'grid.color': '0.1', - 'grid.linestyle': ':', - #'grid.linewidth': 0.5, - 'axes.grid' : True, - #'axes.grid.axis' : 'y', - #'axes.axisbelow': True, - 'axes.titlesize' : 'large', - 'axes.labelsize' : 'x-large', - 'axes.formatter.limits': (-4,4), - 'xtick.labelsize' : 20,#get_tick_font_size_10(), - 'ytick.labelsize' : 20,#get_tick_font_size_10(), - 'lines.linewidth' : 2.0, - 'lines.markeredgewidth' : 0.5, - 'lines.markersize' : 10, - } - - for option_key in options: - matplotlib.rcParams[option_key] = options[option_key] - if 'figure.max_num_figures' in matplotlib.rcParams: - matplotlib.rcParams['figure.max_num_figures'] = 100 - if 'figure.max_open_warning' in matplotlib.rcParams: - matplotlib.rcParams['figure.max_open_warning'] = 100 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/crates/lox-library/README.md b/crates/lox-library/README.md index 009b37d..e05f6fa 100644 --- a/crates/lox-library/README.md +++ b/crates/lox-library/README.md @@ -3,64 +3,6 @@ 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. -### To use the docker environment to build the package: - -``` -./build-lox.sh -./run-lox.sh -``` - -### To run each of the tests used for our experimental results run: - -``` -cargo test --release -- --nocapture TESTNAME > LOGFILE -``` - -Where `TESTNAME > LOGFILE` is one of: - -``` -stats_test_trust_levels > trust_levels.log -stats_test_invitations > invitations.log -stats_test_percent_blockage_migration_05 > blockage_migration05.log -stats_test_percent_blockage_migration_010 > blockage_migration010.log -stats_test_percent_blockage_migration_20 > blockage_migration20.log -stats_test_percent_blockage_migration_25 > blockage_migration25.log -stats_test_percent_blockage_migration_35 > blockage_migration35.log -stats_test_percent_blockage_migration_40 > blockage_migration40.log -stats_test_percent_blockage_migration_45 > blockage_migration45.log -stats_test_percent_blockage_migration_50 > blockage_migration50.log -stats_test_percent_blockage_migration_55 > blockage_migration55.log -stats_test_percent_blockage_migration_60 > blockage_migration60.log -stats_test_percent_blockage_migration_65 > blockage_migration65.log -stats_test_percent_blockage_migration_70 > blockage_migration70.log -stats_test_percent_blockage_migration_75 > blockage_migration75.log -stats_test_percent_blockage_migration_80 > blockage_migration80.log -stats_test_percent_blockage_migration_85 > blockage_migration85.log -stats_test_percent_blockage_migration_90 > blockage_migration90.log -stats_test_percent_blockage_migration_95 > blockage_migration95.log -stats_test_percent_blockage_migration_100 > blockage_migration100.log -``` - -Each test outputs results to the specified log file and takes approximately 20-30 hours to run. However, this can be improved -by passing the `fast` feature. Using this feature, our tests are run for 100 -users instead of 10000 users and will produce results comparable to our -reported results (with larger error margins). To run individual tests with this -flag run: - -``` -cargo test --release --features=fast -- --nocapture TESTNAME > LOGFILE -``` - -We have also included the scripts we used to parse the output from each of the Lox tests in the `Parsing-results` directory. For convenience, copy all of the output log files to the `Parsing-results` directory and run `./parse_data.sh`. This is a python script that uses Python 3.8+ and depends on `numpy`, `matplotlib`, and `pandas` which can be installed with `pip3`. - -To run all tests in fast mode, output the results to the `Parsing-results` directory, and generate the table (`performance_stats.csv`, our Table 4) and graphs (`Blockage-response-time.pdf` and `core-users.pdf`, our Figures 1 and 2) used in our paper, run: - -``` -./run_tests_fast -``` - -This takes 5–6 hours to complete on the 2011-era E7-8870 processor we used for the measurements in the paper. Newer processors will likely take less time. Note that with the `fast` feature, it is possible that some tests may only yield 0 or 1 data points, in which case you will see `0` for the times and/or stddevs in the resulting `performance_stats.csv` table for those tests. - -Note that our implementation is coded such that the reachability certificate expires at 00:00 UTC. A workaround has been included in each test to pause if it is too close to this time so the request won't fail. 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). +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). diff --git a/crates/lox-library/build-lox.sh b/crates/lox-library/build-lox.sh deleted file mode 100755 index 141dda5..0000000 --- a/crates/lox-library/build-lox.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -docker build -t lox . diff --git a/crates/lox-library/run-lox.sh b/crates/lox-library/run-lox.sh deleted file mode 100755 index e95657d..0000000 --- a/crates/lox-library/run-lox.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -docker run --name lox --rm -it lox:latest /bin/bash diff --git a/crates/lox-library/run_tests_fast.sh b/crates/lox-library/run_tests_fast.sh deleted file mode 100755 index 4b43063..0000000 --- a/crates/lox-library/run_tests_fast.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -cargo test --release --features=fast -- --nocapture stats_test_trust_levels > trust_levels.log -cargo test --release --features=fast -- --nocapture stats_test_invitations > invitations.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_05 > blockage_migration05.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_010 > blockage_migration010.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_20 > blockage_migration20.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_25 > blockage_migration25.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_30 > blockage_migration30.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_35 > blockage_migration35.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_40 > blockage_migration40.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_45 > blockage_migration45.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_50 > blockage_migration50.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_55 > blockage_migration55.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_60 > blockage_migration60.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_65 > blockage_migration65.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_70 > blockage_migration70.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_75 > blockage_migration75.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_80 > blockage_migration80.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_85 > blockage_migration85.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_90 > blockage_migration90.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_95 > blockage_migration95.log -cargo test --release --features=fast -- --nocapture stats_test_percent_blockage_migration_100 > blockage_migration100.log -echo "Completed all tests, now parsing results" -mv *.log Parsing-results -cd Parsing-results -./parse_data.sh -echo "Parse results are in the Parsing-results folder." - diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 5627d9a..fe696c6 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -4,18 +4,9 @@ BridgeLine::random() or private fields */ use super::bridge_table::{BridgeLine, BRIDGE_BYTES}; use super::proto::*; use super::*; -use chrono::{DateTime, NaiveTime, Timelike, Utc}; use rand::Rng; -use statistical::{mean, standard_deviation}; -use std::collections::HashSet; -use std::thread; use std::time::{Duration, Instant}; -#[cfg(feature = "fast")] -const USERS: usize = 100; -#[cfg(not(feature = "fast"))] -const USERS: usize = 10000; - struct PerfStat { // Report performance metrics for each test req_len: usize, @@ -995,1049 +986,10 @@ fn test_blockage_migration() { assert!(th.ba.verify_lox(&cred4)); } -#[test] -fn stats_test_trust_levels() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - - let mut promo_req_size: Vec = Vec::new(); - let mut promo_resp_size: Vec = Vec::new(); - let mut promo_req_time: Vec = Vec::new(); - let mut promo_resp_time: Vec = Vec::new(); - let mut promo_resp_handle_time: Vec = Vec::new(); - let mut mig_req_size: Vec = Vec::new(); - let mut mig_resp_size: Vec = Vec::new(); - let mut mig_req_time: Vec = Vec::new(); - let mut mig_resp_time: Vec = Vec::new(); - let mut mig_resp_handle_time: Vec = Vec::new(); - let mut sec_req_size: Vec = Vec::new(); - let mut sec_resp_size: Vec = Vec::new(); - let mut sec_req_time: Vec = Vec::new(); - let mut sec_resp_time: Vec = Vec::new(); - let mut sec_resp_handle_time: Vec = Vec::new(); - let mut three_req_size: Vec = Vec::new(); - let mut three_resp_size: Vec = Vec::new(); - let mut three_req_time: Vec = Vec::new(); - let mut three_resp_time: Vec = Vec::new(); - let mut three_resp_handle_time: Vec = Vec::new(); - let mut four_req_size: Vec = Vec::new(); - let mut four_resp_size: Vec = Vec::new(); - let mut four_req_time: Vec = Vec::new(); - let mut four_resp_time: Vec = Vec::new(); - let mut four_resp_handle_time: Vec = Vec::new(); - let mut open_req_size: Vec = Vec::new(); - let mut open_resp_size: Vec = Vec::new(); - let mut open_req_time: Vec = Vec::new(); - let mut open_resp_time: Vec = Vec::new(); - let mut open_resp_handle_time: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let (open_perf_stat, cred) = th.open_invite(); - th.advance_days(30); - let (tp_perf_stat, migcred) = th.trust_promotion(&cred.0); - let (mig_perf_stat, cred1) = th.level0_migration(&cred.0, &migcred); - th.advance_days(14); - let (sec_perf_stat, cred2) = th.level_up(&cred1); - th.advance_days(28); - let (three_perf_stat, cred3) = th.level_up(&cred2); - th.advance_days(56); - let (four_perf_stat, _) = th.level_up(&cred3); - open_req_size.push(open_perf_stat.req_len as f64); - open_req_time.push(open_perf_stat.req_t.as_secs_f64()); - open_resp_size.push(open_perf_stat.resp_len as f64); - open_resp_time.push(open_perf_stat.resp_t.as_secs_f64()); - open_resp_handle_time.push(open_perf_stat.resp_handle_t.as_secs_f64()); - promo_req_size.push(tp_perf_stat.req_len as f64); - promo_req_time.push(tp_perf_stat.req_t.as_secs_f64()); - promo_resp_size.push(tp_perf_stat.resp_len as f64); - promo_resp_time.push(tp_perf_stat.resp_t.as_secs_f64()); - promo_resp_handle_time.push(tp_perf_stat.resp_handle_t.as_secs_f64()); - mig_req_size.push(mig_perf_stat.req_len as f64); - mig_req_time.push(mig_perf_stat.req_t.as_secs_f64()); - mig_resp_size.push(mig_perf_stat.resp_len as f64); - mig_resp_time.push(mig_perf_stat.resp_t.as_secs_f64()); - mig_resp_handle_time.push(mig_perf_stat.resp_handle_t.as_secs_f64()); - sec_req_size.push(sec_perf_stat.req_len as f64); - sec_req_time.push(sec_perf_stat.req_t.as_secs_f64()); - sec_resp_size.push(sec_perf_stat.resp_len as f64); - sec_resp_time.push(sec_perf_stat.resp_t.as_secs_f64()); - sec_resp_handle_time.push(sec_perf_stat.resp_handle_t.as_secs_f64()); - three_req_size.push(three_perf_stat.req_len as f64); - three_req_time.push(three_perf_stat.req_t.as_secs_f64()); - three_resp_size.push(three_perf_stat.resp_len as f64); - three_resp_time.push(three_perf_stat.resp_t.as_secs_f64()); - three_resp_handle_time.push(three_perf_stat.resp_handle_t.as_secs_f64()); - four_req_size.push(four_perf_stat.req_len as f64); - four_req_time.push(four_perf_stat.req_t.as_secs_f64()); - four_resp_size.push(four_perf_stat.resp_len as f64); - four_resp_time.push(four_perf_stat.resp_t.as_secs_f64()); - four_resp_handle_time.push(four_perf_stat.resp_handle_t.as_secs_f64()); - } - - println!("\n***START: {}*3*2 BUCKETS LEVELS***\n", x); - println!("\n----OPEN-INVITATION-{}---\n", x); - print_stats_test_results( - open_req_size, - open_req_time, - open_resp_size, - open_resp_time, - open_resp_handle_time, - ); - - println!("\n----TRUST-PROMOTION-1: 30 days-{}---\n", x); - print_stats_test_results( - promo_req_size, - promo_req_time, - promo_resp_size, - promo_resp_time, - promo_resp_handle_time, - ); - - println!("\n----TRUST-MIGRATION-0: 30 days-{}---\n", x); - print_stats_test_results( - mig_req_size, - mig_req_time, - mig_resp_size, - mig_resp_time, - mig_resp_handle_time, - ); - - println!("\n----LEVEL-UP-2: 44 days-{}---\n", x); - print_stats_test_results( - sec_req_size, - sec_req_time, - sec_resp_size, - sec_resp_time, - sec_resp_handle_time, - ); - - println!("\n----LEVEL-UP-3: 72 days---{}---\n", x); - print_stats_test_results( - three_req_size, - three_req_time, - three_resp_size, - three_resp_time, - three_resp_handle_time, - ); - - println!("\n----LEVEL-UP-4: 128 days---{}---\n", x); - print_stats_test_results( - four_req_size, - four_req_time, - four_resp_size, - four_resp_time, - four_resp_handle_time, - ); - } -} - -#[test] -fn stats_test_invitations() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - - let mut req_size: Vec = Vec::new(); - let mut resp_size: Vec = Vec::new(); - let mut req_time: Vec = Vec::new(); - let mut resp_time: Vec = Vec::new(); - let mut resp_handle_time: Vec = Vec::new(); - let mut red_req_size: Vec = Vec::new(); - let mut red_resp_size: Vec = Vec::new(); - let mut red_req_time: Vec = Vec::new(); - let mut red_resp_time: Vec = Vec::new(); - let mut red_resp_handle_time: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - th.advance_days(28); - let (perf_stat, (_, invite)) = th.issue_invite(&cred2); - let (bob_perf_stat, _) = th.redeem_invite(&invite); - req_size.push(perf_stat.req_len as f64); - req_time.push(perf_stat.req_t.as_secs_f64()); - resp_size.push(perf_stat.resp_len as f64); - resp_time.push(perf_stat.resp_t.as_secs_f64()); - resp_handle_time.push(perf_stat.resp_handle_t.as_secs_f64()); - red_req_size.push(bob_perf_stat.req_len as f64); - red_req_time.push(bob_perf_stat.req_t.as_secs_f64()); - red_resp_size.push(bob_perf_stat.resp_len as f64); - red_resp_time.push(bob_perf_stat.resp_t.as_secs_f64()); - red_resp_handle_time.push(bob_perf_stat.resp_handle_t.as_secs_f64()); - } - - println!("\n***START: {}*3*2 BUCKETS INVITATIONS***\n", x); - println!("\n----ISSUE-INVITATION-{}---\n", x); - print_stats_test_results(req_size, req_time, resp_size, resp_time, resp_handle_time); - - println!("\n----REDEEM-INVITATION-{}---\n", x); - print_stats_test_results( - red_req_size, - red_req_time, - red_resp_size, - red_resp_time, - red_resp_handle_time, - ); - } -} - -#[test] -fn stats_test_percent_blockage_migration_05() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 5***\n", x); - block_bridges(&mut th, 5, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_010() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 10***\n", x); - block_bridges(&mut th, 10, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_15() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 15***\n", x); - block_bridges(&mut th, 15, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_20() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 20***\n", x); - block_bridges(&mut th, 20, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_25() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 25***\n", x); - block_bridges(&mut th, 25, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_30() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 30***\n", x); - block_bridges(&mut th, 30, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_35() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 35***\n", x); - block_bridges(&mut th, 35, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_40() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 40***\n", x); - block_bridges(&mut th, 40, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_45() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 45***\n", x); - block_bridges(&mut th, 45, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_50() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 50***\n", x); - block_bridges(&mut th, 50, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_55() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 55***\n", x); - block_bridges(&mut th, 55, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_60() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 60***\n", x); - block_bridges(&mut th, 60, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_65() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 65***\n", x); - block_bridges(&mut th, 65, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_70() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 70***\n", x); - block_bridges(&mut th, 70, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_75() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 75***\n", x); - block_bridges(&mut th, 75, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_80() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 80***\n", x); - block_bridges(&mut th, 80, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_85() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 85***\n", x); - block_bridges(&mut th, 85, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_90() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 90***\n", x); - block_bridges(&mut th, 90, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_95() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - - println!("\n***START: {}*3*2 BUCKETS 95***\n", x); - block_bridges(&mut th, 95, credentials); - } -} - -#[test] -fn stats_test_percent_blockage_migration_100() { - let buckets: Vec = vec![150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500]; - - for x in buckets { - let mut th = TestHarness::new_buckets(x, x); - let mut credentials: Vec = Vec::new(); - for _ in 0..USERS { - let h: NaiveTime = DateTime::time(&Utc::now()); - if h.hour() == 23 && h.minute() == 59 { - println!("Wait for UTC 00:00"); - thread::sleep(Duration::new(60, 0)); - println!("Ready to work again"); - } - let cred = th.open_invite().1 .0; - th.advance_days(30); - let (_, migcred) = th.trust_promotion(&cred); - let (_, cred1) = th.level0_migration(&cred, &migcred); - th.advance_days(14); - let (_, cred2) = th.level_up(&cred1); - let (_, (cred2a, invite)) = th.issue_invite(&cred2); - let (_, bob_cred) = th.redeem_invite(&invite); - th.advance_days(28); - let (_, _) = th.level_up(&bob_cred); - let (_, cred3) = th.level_up(&cred2a); - credentials.push(cred3); - } - println!("\n***START: {}*3*2 BUCKETS 100***\n", x); - block_bridges(&mut th, 100, credentials); - } -} - -/// Blocks a percentage of the bridges for the passed Test Harness -/// excluding the hot spare buckets as they will not have been handed out. -/// The logic assumes hot spare buckets are appended to the end of the bridge_table -/// bucket list. - -fn block_bridges(th: &mut TestHarness, percentage: usize, credentials: Vec) { - let blockable_num = th.ba.bridge_table.buckets.len() - - th.ba.bridge_table.spares.len() - - th.bdb.openinv_buckets.len(); - let blockable_range = th.ba.bridge_table.buckets.len() - th.ba.bridge_table.spares.len(); - let to_block: usize = blockable_num * percentage / 100; - let mut block_index: HashSet = HashSet::new(); - let mut rng = rand::thread_rng(); - - while block_index.len() < to_block { - let rand_num = rng.gen_range(0, blockable_range); - if !th.bdb.openinv_buckets.contains(&(rand_num as u32)) { - block_index.insert(rand_num); - } - } - - for index in block_index { - let b0 = th.ba.bridge_table.buckets[index][0]; - let b1 = th.ba.bridge_table.buckets[index][1]; - let b2 = th.ba.bridge_table.buckets[index][2]; - th.ba.bridge_unreachable(&b0, &mut th.bdb); - th.ba.bridge_unreachable(&b1, &mut th.bdb); - th.ba.bridge_unreachable(&b2, &mut th.bdb); - } - - let mut req_size: Vec = Vec::new(); - let mut resp_size: Vec = Vec::new(); - let mut req_time: Vec = Vec::new(); - let mut resp_time: Vec = Vec::new(); - let mut resp_handle_time: Vec = Vec::new(); - let mut red_req_size: Vec = Vec::new(); - let mut red_resp_size: Vec = Vec::new(); - let mut red_req_time: Vec = Vec::new(); - let mut red_resp_time: Vec = Vec::new(); - let mut red_resp_handle_time: Vec = Vec::new(); - for cred in credentials { - let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap(); - let encbuckets = th.ba.enc_bridge_table(); - let bucket = - bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap(); - - let mut count = 0; - for bridge_line in &bucket.0 { - if th.ba.bridge_table.reachable.contains_key(bridge_line) { - count += 1; - } - } - - if count < 2 { - let (perf_stat, migration) = th.check_blockage(&cred); - let (block_perf_stat, _) = th.blockage_migration(&cred, &migration); - req_size.push(perf_stat.req_len as f64); - req_time.push(perf_stat.req_t.as_secs_f64()); - resp_size.push(perf_stat.resp_len as f64); - resp_time.push(perf_stat.resp_t.as_secs_f64()); - resp_handle_time.push(perf_stat.resp_handle_t.as_secs_f64()); - red_req_size.push(block_perf_stat.req_len as f64); - red_req_time.push(block_perf_stat.req_t.as_secs_f64()); - red_resp_size.push(block_perf_stat.resp_len as f64); - red_resp_time.push(block_perf_stat.resp_t.as_secs_f64()); - red_resp_handle_time.push(block_perf_stat.resp_handle_t.as_secs_f64()); - } - } - - println!("\n----CHECK-BLOCKAGE-{}----\n", percentage); - print_stats_test_results(req_size, req_time, resp_size, resp_time, resp_handle_time); - - println!("\n----BLOCKAGE-MIGRATION-{}----\n", percentage); - print_stats_test_results( - red_req_size, - red_req_time, - red_resp_size, - red_resp_time, - red_resp_handle_time, - ); -} - fn print_test_results(perf_stat: PerfStat) { println!("Request size = {:?} bytes", perf_stat.req_len); println!("Request time = {:?}", perf_stat.req_t); println!("Response size = {:?} bytes", perf_stat.resp_len); println!("Response time = {:?}", perf_stat.resp_t); println!("Response handle time = {:?}", perf_stat.resp_handle_t); -} - -//fn print_time_test_results(perf_stat: PerfStat) { -// println!("Request time = {:?}", perf_stat.req_t); -// println!("Response time = {:?}", perf_stat.resp_t); -// println!("Response handle time = {:?}", perf_stat.resp_handle_t); -//} - -fn print_stats_test_results( - req_size: Vec, - req_time: Vec, - resp_size: Vec, - resp_time: Vec, - resp_handle_time: Vec, -) { - let mean_req_size = if req_size.len() > 0 { - mean(&req_size) - } else { - 0.0 - }; - let req_std_dev = if req_size.len() > 1 { - standard_deviation(&req_size, Some(mean_req_size)) - } else { - 0.0 - }; - let mean_req_time = if req_time.len() > 0 { - mean(&req_time) - } else { - 0.0 - }; - let req_time_std_dev = if req_time.len() > 1 { - standard_deviation(&req_time, Some(mean_req_time)) - } else { - 0.0 - }; - let mean_resp_size = if resp_size.len() > 0 { - mean(&resp_size) - } else { - 0.0 - }; - let resp_std_dev = if resp_size.len() > 1 { - standard_deviation(&resp_size, Some(mean_resp_size)) - } else { - 0.0 - }; - let mean_resp_time = if resp_time.len() > 0 { - mean(&resp_time) - } else { - 0.0 - }; - let resp_time_std_dev = if resp_time.len() > 1 { - standard_deviation(&resp_time, Some(mean_resp_time)) - } else { - 0.0 - }; - let mean_resp_handle_time = if resp_handle_time.len() > 0 { - mean(&resp_handle_time) - } else { - 0.0 - }; - let resp_handle_time_std_dev = if resp_handle_time.len() > 1 { - standard_deviation(&resp_handle_time, Some(mean_resp_handle_time)) - } else { - 0.0 - }; - - println!("Average request size = {} bytes", mean_req_size); - println!("Request size standard deviation = {} bytes", req_std_dev); - println!( - "Average request time = {:?}", - Duration::from_secs_f64(mean_req_time) - ); - println!( - "Request time standard deviation = {:?}", - Duration::from_secs_f64(req_time_std_dev) - ); - println!("Average response size = {} bytes", mean_resp_size); - println!("Response standard deviation = {} bytes", resp_std_dev); - println!( - "Average response time = {:?}", - Duration::from_secs_f64(mean_resp_time) - ); - println!( - "Response time standard deviation = {:?}", - Duration::from_secs_f64(resp_time_std_dev) - ); - println!( - "Average response handling time = {:?}", - Duration::from_secs_f64(mean_resp_handle_time) - ); - println!( - "Response handling time standard deviation = {:?}", - Duration::from_secs_f64(resp_handle_time_std_dev) - ); -} +} \ No newline at end of file