123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- mod client_lib;
- use client_lib::*;
- mod client_net;
- use client_net::HyperNet;
- use curve25519_dalek::scalar::Scalar;
- use getopts::Options;
- use lox_library::bridge_table::BridgeLine;
- use lox_library::bridge_table::MAX_BRIDGES_PER_BUCKET;
- use lox_library::scalar_u32;
- use lox_library::IssuerPubKey;
- use serde::Serialize;
- use std::env::args;
- use std::fs::File;
- use std::io::Write;
- use std::path::Path;
- use std::str::FromStr;
- // Prints the argument details for this program
- fn print_usage(program: &str, opts: Options) {
- let brief = format!("Usage: {} [options]", program);
- print!("{}", opts.usage(&brief));
- }
- // Helper function to save serializable objects to files
- fn save_object<T: Serialize>(obj: T, filename: &str) {
- let mut outfile = File::create(filename).expect(&("Failed to create ".to_string() + filename));
- write!(outfile, "{}", serde_json::to_string(&obj).unwrap())
- .expect(&("Failed to write to ".to_string() + filename));
- }
- #[tokio::main]
- async fn main() {
- let args: Vec<String> = args().collect();
- // files used to store various data
- let bucket_filename = "bucket.json";
- let invite_filename = "invite.json";
- let lox_auth_pubkeys_filename = "lox_auth_pubkeys.json";
- let lox_cred_filename = "lox_cred.json";
- let mut opts = Options::new();
- opts.optflag("h", "help", "print this help menu");
- //#[cfg(test)]
- opts.optopt(
- "A",
- "advance-days",
- "increase server days by NUM_DAYS",
- "NUM_DAYS",
- );
- opts.optflag("I", "invite", "generate invitation for a friend");
- opts.optflag("L", "level-up", "increase trust level");
- opts.optflag("N", "new-lox-cred", "get a new Lox Credential");
- opts.optflag("R", "redeem", "redeem invitation");
- opts.optopt(
- "",
- "server",
- "Lox Auth server address [http://localhost:8001]",
- "ADDR",
- );
- let matches = match opts.parse(&args[1..]) {
- Ok(m) => m,
- Err(f) => {
- panic!("{}", f.to_string())
- }
- };
- if matches.opt_present("h") {
- print_usage(&args[0], opts);
- return;
- }
- let net = if matches.opt_present("server") {
- HyperNet {
- hostname: matches.opt_str("server").unwrap(),
- }
- } else {
- HyperNet {
- hostname: "http://localhost:8001".to_string(),
- }
- };
- // Advance days on server (TESTING ONLY)
- //#[cfg(test)]
- if matches.opt_present("A") {
- let days: u16 = u16::from_str(matches.opt_str("A").unwrap().as_str()).unwrap();
- let today: u32 = advance_days(&net, days).await;
- println!("Today's date according to the server: {}", today);
- }
- // Get Lox Authority public keys
- let lox_auth_pubkeys: Vec<IssuerPubKey> = if Path::new(lox_auth_pubkeys_filename).exists() {
- // read in file
- let lox_auth_pubkeys_infile = File::open(lox_auth_pubkeys_filename).unwrap();
- serde_json::from_reader(lox_auth_pubkeys_infile).unwrap()
- } else {
- // download from Lox Auth
- let pubkeys = get_lox_auth_keys(&net).await;
- // save to file for next time
- save_object(&pubkeys, &lox_auth_pubkeys_filename);
- pubkeys
- };
- // Get Lox Credential and Bucket
- let (lox_cred, bucket) = if matches.opt_present("R") && Path::new(invite_filename).exists() {
- // redeem invite
- let invite_infile = File::open(invite_filename).unwrap();
- let invite = serde_json::from_reader(invite_infile).unwrap();
- let cred = redeem_invite(
- &net,
- &invite,
- get_lox_pub(&lox_auth_pubkeys),
- get_invitation_pub(&lox_auth_pubkeys),
- )
- .await;
- let bucket = get_bucket(&net, &cred).await;
- // save to files for future use
- save_object(&cred, &lox_cred_filename);
- save_object(&bucket, &bucket_filename);
- (cred, bucket)
- } else if matches.opt_present("N")
- || !Path::new(lox_cred_filename).exists()
- || !Path::new(bucket_filename).exists()
- {
- // get new Lox Credential
- let open_invite = get_open_invitation(&net).await;
- let (cred, bl) =
- get_lox_credential(&net, &open_invite, get_lox_pub(&lox_auth_pubkeys)).await;
- let mut bucket = [BridgeLine::default(); MAX_BRIDGES_PER_BUCKET];
- // note: this is a bucket with one real bridgeline and n-1
- // default (zeroed out) bridgelines
- bucket[0] = bl;
- // save to files for future use
- save_object(&cred, &lox_cred_filename);
- save_object(&bucket, &bucket_filename);
- (cred, bucket)
- } else {
- // Read existing Lox Credential and BridgeLine from files
- let cred = serde_json::from_reader(File::open(lox_cred_filename).unwrap()).unwrap();
- let bucket = serde_json::from_reader(File::open(bucket_filename).unwrap()).unwrap();
- (cred, bucket)
- };
- let lox_cred = if matches.opt_present("L") {
- let old_level = get_cred_trust_level(&lox_cred);
- // If trust level is 0, do trust promotion, otherwise level up.
- let cred = if old_level == 0 {
- if eligible_for_trust_promotion(&net, &lox_cred).await {
- let migration_cred =
- trust_promotion(&net, &lox_cred, get_lox_pub(&lox_auth_pubkeys)).await;
- let cred = trust_migration(
- &net,
- &lox_cred,
- &migration_cred,
- get_lox_pub(&lox_auth_pubkeys),
- get_migration_pub(&lox_auth_pubkeys),
- )
- .await;
- cred
- } else {
- lox_cred
- }
- } else {
- if eligible_for_level_up(&net, &lox_cred).await {
- let encbuckets = get_reachability_credential(&net).await;
- let cred = level_up(
- &net,
- &lox_cred,
- &encbuckets,
- get_lox_pub(&lox_auth_pubkeys),
- get_reachability_pub(&lox_auth_pubkeys),
- )
- .await;
- cred
- } else {
- lox_cred
- }
- };
- save_object(&cred, &lox_cred_filename);
- let new_level = get_cred_trust_level(&cred);
- if new_level > old_level {
- println!("Old level: {}\nNew level: {}", old_level, new_level);
- } else if new_level == old_level {
- println!("Unable to level up. Current level: {}", new_level);
- }
- cred
- } else {
- lox_cred
- };
- // Invite a friend
- let lox_cred = if matches.opt_present("I") {
- if scalar_u32(&lox_cred.invites_remaining).unwrap() > 0 {
- let (cred, invite) = issue_invite(
- &net,
- &lox_cred,
- &get_reachability_credential(&net).await,
- get_lox_pub(&lox_auth_pubkeys),
- get_reachability_pub(&lox_auth_pubkeys),
- get_invitation_pub(&lox_auth_pubkeys),
- )
- .await;
- // TODO: Make this unique per-run (e.g., add timestamp)
- save_object(&invite, &invite_filename);
- save_object(&cred, &lox_cred_filename);
- println!("Invite saved in {}", &invite_filename);
- println!(
- "Invites left: {}",
- scalar_u32(&cred.invites_remaining).unwrap()
- );
- cred
- } else {
- println!("No invites left");
- lox_cred
- }
- } else {
- lox_cred
- };
- }
|