user.rs 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. // User behavior in simulation
  2. use crate::{
  3. bridge::Bridge,
  4. censor::{Censor, Secrecy::*, Totality::*},
  5. config::Config,
  6. };
  7. use anyhow::{anyhow, Result};
  8. use lox_cli::{networking::*, *};
  9. use lox_library::{
  10. bridge_table::BridgeLine,
  11. cred::{Invitation, Lox},
  12. proto::check_blockage::MIN_TRUST_LEVEL,
  13. scalar_u32,
  14. };
  15. use rand::Rng;
  16. use std::collections::{HashMap, HashSet};
  17. use troll_patrol::{
  18. get_date, negative_report::NegativeReport, positive_report::PositiveReport, BridgeDistributor,
  19. };
  20. use x25519_dalek::PublicKey;
  21. // Helper function to probabilistically return true or false
  22. pub fn event_happens(probability: f64) -> bool {
  23. let mut rng = rand::thread_rng();
  24. let num: f64 = rng.gen_range(0.0..1.0);
  25. num < probability
  26. }
  27. // Make sure each bridge is in global bridges set and known by censor
  28. pub fn give_bucket_to_censor(
  29. bucket: &[BridgeLine],
  30. bridges: &mut HashMap<[u8; 20], Bridge>,
  31. censor: &mut Censor,
  32. ) {
  33. for bridgeline in bucket {
  34. if *bridgeline != BridgeLine::default() {
  35. let fingerprint = bridgeline.get_hashed_fingerprint();
  36. if !bridges.contains_key(&fingerprint) {
  37. let bridge = Bridge::from_bridge_line(&bridgeline);
  38. bridges.insert(fingerprint, bridge);
  39. }
  40. censor.learn_bridge(&fingerprint);
  41. }
  42. }
  43. }
  44. // Check if bucket is blocked, according to the LA (regardless of
  45. // whether the censor actually blocks the bridges)
  46. pub fn bucket_blocked_lox(bucket: &[BridgeLine], bridges: &HashMap<[u8; 20], Bridge>) -> bool {
  47. // Count number of non-default bridges (either 1 or 3)
  48. let mut num_real_bridges = 0;
  49. let mut num_blocked_bridges = 0;
  50. for bridge in bucket {
  51. if *bridge != BridgeLine::default() {
  52. match bridges.get(&bridge.get_hashed_fingerprint()) {
  53. Some(b) => {
  54. num_real_bridges += 1;
  55. if b.troll_patrol_blocked() {
  56. num_blocked_bridges += 1;
  57. }
  58. }
  59. None => {
  60. // Something went wrong, I guess
  61. println!(
  62. "Tried to check if bridge was blocked before it was added to simulation"
  63. );
  64. }
  65. }
  66. }
  67. }
  68. // Return true if open-entry bucket with a blocked bridge or
  69. // invite-only bucket with 2+ blocked bridges
  70. num_real_bridges == 1 && num_blocked_bridges == 1
  71. || num_real_bridges == 3 && num_blocked_bridges >= 2
  72. }
  73. // Check if bucket contains a bridge that has ever been distributed to a
  74. // real user
  75. pub fn bucket_has_been_distributed(
  76. bucket: &[BridgeLine],
  77. bridges: &HashMap<[u8; 20], Bridge>,
  78. ) -> bool {
  79. for bridge in bucket {
  80. if *bridge != BridgeLine::default() {
  81. match bridges.get(&bridge.get_hashed_fingerprint()) {
  82. Some(b) => {
  83. if b.has_been_distributed() {
  84. return true;
  85. }
  86. }
  87. None => {
  88. // Something went wrong, I guess
  89. println!(
  90. "Tried to check if bridge had been distributed before it was added to simulation"
  91. );
  92. }
  93. }
  94. }
  95. }
  96. false
  97. }
  98. pub struct User {
  99. // Does this user cooperate with a censor?
  100. pub is_censor: bool,
  101. // The user always has a primary credential. If this credential's bucket is
  102. // blocked, the user may replace it or temporarily hold two credentials
  103. // while waiting to migrate from the primary credential.
  104. pub primary_cred: Lox,
  105. secondary_cred: Option<Lox>,
  106. // Does the user submit reports to Troll Patrol?
  107. submits_reports: bool,
  108. // How likely is this user to use bridges on a given day? This has
  109. // been converted to a global parameter (prob_user_connects), but we
  110. // still leave the user implementation for now in case we want to
  111. // switch back to it.
  112. prob_use_bridges: f64,
  113. // If the censor implements partial blocking, is the user blocked?
  114. in_censorship_range: bool,
  115. // Track date the user joined and whether they're able to connect
  116. pub join_date: u32,
  117. pub able_to_connect: bool,
  118. // Attempted to connect today
  119. pub attempted_connection: bool,
  120. }
  121. impl User {
  122. pub async fn new(
  123. config: &Config,
  124. is_censor: bool,
  125. bridges: &mut HashMap<[u8; 20], Bridge>,
  126. censor: &mut Censor,
  127. ) -> Result<Self> {
  128. if censor.is_active() && !is_censor {
  129. return Err(anyhow!("Censor is active; open invites disabled"));
  130. }
  131. let cred = Self::get_new_credential(&config).await?.0;
  132. // Decide how likely this user is to use bridges on a given day
  133. // and whether they submit reports
  134. let (prob_use_bridges, submits_reports) = if is_censor {
  135. (0.0, false)
  136. } else {
  137. // Use global value
  138. let prob_use_bridges = config.prob_user_connects;
  139. let submits_reports = event_happens(config.prob_user_submits_reports);
  140. (prob_use_bridges, submits_reports)
  141. };
  142. let in_censorship_range = if config.censor_totality == Partial {
  143. event_happens(config.censor_partial_blocking_percent)
  144. } else {
  145. true
  146. };
  147. let mut result = Self {
  148. is_censor,
  149. primary_cred: cred,
  150. secondary_cred: None,
  151. submits_reports: submits_reports,
  152. prob_use_bridges: prob_use_bridges,
  153. in_censorship_range,
  154. join_date: get_date(),
  155. able_to_connect: false,
  156. attempted_connection: true,
  157. };
  158. // Immediately download and try to use our bridges, or report them to the censor.
  159. let (bucket, _reachcred) = get_bucket(&config.la_net, &result.primary_cred).await?;
  160. if is_censor {
  161. // Give bridges to censor
  162. give_bucket_to_censor(&bucket, bridges, censor);
  163. // Various conditions to avoid creating censor users if we don't need to
  164. // If the bucket is already marked blocked, don't create this user
  165. if bucket_blocked_lox(&bucket, bridges) {
  166. return Err(anyhow!("Bucket blocked, don't create new censor user"));
  167. }
  168. // If the bucket has never been distributed to a real user, don't create this user
  169. if !bucket_has_been_distributed(&bucket, bridges) {
  170. return Err(anyhow!(
  171. "Bucket never distributed to a real user, don't create new censor user"
  172. ));
  173. }
  174. // If we already have enough agents with this bucket, don't create this user
  175. if censor.num_agents(&result.primary_cred.bucket) > config.censor_max_pr {
  176. return Err(anyhow!(
  177. "We already have enough censor users with this bucket"
  178. ));
  179. }
  180. // If we haven't returned yet, add this user to censor's list
  181. censor.add_agent(&result.primary_cred.bucket);
  182. } else {
  183. // Test bridges to see if they work
  184. let (s, f) = result.test_bridges(&bucket, config, bridges, censor);
  185. // Our bridge worked! Yay!
  186. if !s.is_empty() {
  187. result.able_to_connect = true;
  188. }
  189. // Report any failures if we submit reports
  190. if submits_reports {
  191. for bl in f {
  192. let mut negative_reports = Vec::<NegativeReport>::new();
  193. negative_reports.push(NegativeReport::from_bridgeline(
  194. bl,
  195. config.country.to_string(),
  196. BridgeDistributor::Lox,
  197. ));
  198. Self::send_negative_reports(&config, negative_reports).await?;
  199. }
  200. }
  201. }
  202. // Return our new user
  203. Ok(result)
  204. }
  205. // Get an invite if able
  206. pub async fn get_invite(
  207. &mut self,
  208. config: &Config,
  209. bridges: &mut HashMap<[u8; 20], Bridge>,
  210. censor: &mut Censor,
  211. ) -> Result<Invitation> {
  212. let etable = get_reachability_credential(&config.la_net).await?;
  213. let (new_cred, invite) = issue_invite(
  214. &config.la_net,
  215. &self.primary_cred,
  216. &etable,
  217. get_lox_pub(&config.la_pubkeys),
  218. get_reachability_pub(&config.la_pubkeys),
  219. get_invitation_pub(&config.la_pubkeys),
  220. )
  221. .await?;
  222. self.primary_cred = new_cred;
  223. // If user cooperates with censor, give bridges and credential
  224. // now. Otherwise, wait until the user actually wants to use
  225. // Tor.
  226. if self.is_censor {
  227. let (bucket, _reachcred) = get_bucket(&config.la_net, &self.primary_cred).await?;
  228. give_bucket_to_censor(&bucket, bridges, censor);
  229. }
  230. Ok(invite)
  231. }
  232. pub async fn from_invite(
  233. invite: Invitation,
  234. config: &Config,
  235. is_censor: bool,
  236. bridges: &mut HashMap<[u8; 20], Bridge>,
  237. censor: &mut Censor,
  238. ) -> Result<Self> {
  239. let cred = redeem_invite(
  240. &config.la_net,
  241. &invite,
  242. get_lox_pub(&config.la_pubkeys),
  243. get_invitation_pub(&config.la_pubkeys),
  244. )
  245. .await?
  246. .0;
  247. // Decide how likely this user is to use bridges on a given day
  248. // and whether they submit reports
  249. let (prob_use_bridges, submits_reports) = if is_censor {
  250. (0.0, false)
  251. } else {
  252. // Use global value
  253. let prob_use_bridges = config.prob_user_connects;
  254. let submits_reports = event_happens(config.prob_user_submits_reports);
  255. (prob_use_bridges, submits_reports)
  256. };
  257. let in_censorship_range = if config.censor_totality == Partial {
  258. event_happens(config.censor_partial_blocking_percent)
  259. } else {
  260. true
  261. };
  262. let mut result = Self {
  263. is_censor,
  264. primary_cred: cred,
  265. secondary_cred: None,
  266. submits_reports: submits_reports,
  267. prob_use_bridges: prob_use_bridges,
  268. in_censorship_range,
  269. join_date: get_date(),
  270. able_to_connect: false,
  271. attempted_connection: true,
  272. };
  273. let (bucket, _reachcred) = get_bucket(&config.la_net, &result.primary_cred).await?;
  274. if is_censor {
  275. give_bucket_to_censor(&bucket, bridges, censor);
  276. // Various conditions to avoid creating censor users unnecessarily
  277. // If the bucket is already marked blocked, don't create this user
  278. if bucket_blocked_lox(&bucket, bridges) {
  279. return Err(anyhow!("Bucket blocked, don't create new censor user"));
  280. }
  281. // If we already have enough agents with this bucket, don't create this user
  282. if censor.num_agents(&result.primary_cred.bucket) > config.censor_max_pr {
  283. return Err(anyhow!(
  284. "We already have enough censor users with this bucket"
  285. ));
  286. }
  287. // If we haven't returned yet, add this user to censor's list
  288. censor.add_agent(&result.primary_cred.bucket);
  289. } else {
  290. let (s, f) = result.test_bridges(&bucket, config, bridges, censor);
  291. // Our bridge worked! Yay!
  292. if !s.is_empty() {
  293. result.able_to_connect = true;
  294. }
  295. // Report any failures if we submit reports
  296. if submits_reports {
  297. for bl in f {
  298. let mut negative_reports = Vec::<NegativeReport>::new();
  299. negative_reports.push(NegativeReport::from_bridgeline(
  300. bl,
  301. config.country.to_string(),
  302. BridgeDistributor::Lox,
  303. ));
  304. Self::send_negative_reports(&config, negative_reports).await?;
  305. }
  306. }
  307. }
  308. Ok(result)
  309. }
  310. // Attempt to "connect" to the bridge, returns true if successful.
  311. // Note that this does not involve making a real connection to a
  312. // real bridge.
  313. pub fn connect(
  314. in_censorship_range: bool,
  315. config: &Config,
  316. bridge: &mut Bridge,
  317. censor: &Censor,
  318. ) -> bool {
  319. if censor.blocks_bridge(config, &bridge.fingerprint) {
  320. if config.censor_totality == Full
  321. || config.censor_totality == Partial && in_censorship_range
  322. {
  323. // If censor tries to hide its censorship, record a
  324. // false connection
  325. if config.censor_secrecy == Hiding {
  326. bridge.connect_total();
  327. }
  328. // Return false because the connection failed
  329. return false;
  330. } else if config.censor_totality == Throttling {
  331. // With some probability, the user connects but gives up
  332. // because there is too much interference. In this case,
  333. // a real connection occurs, but we treat it like a
  334. // false connection from the censor.
  335. if event_happens(config.prob_user_treats_throttling_as_blocking) {
  336. bridge.connect_total();
  337. // Return false because there was interference
  338. // detected in the connection
  339. return false;
  340. }
  341. }
  342. }
  343. // Connection may randomly fail, without censor intervention
  344. let mut connection_fails = true;
  345. // The user retries some number of times
  346. for _ in 0..=config.num_connection_retries {
  347. if !event_happens(config.prob_connection_fails) {
  348. connection_fails = false;
  349. break;
  350. }
  351. }
  352. if connection_fails {
  353. return false;
  354. }
  355. // If we haven't returned yet, the connection succeeded
  356. bridge.connect_real();
  357. true
  358. }
  359. // Given a Lox credential, download its bucket, test its bridges, and
  360. // return sets of working and non-working bridges
  361. pub fn test_bridges(
  362. &mut self,
  363. bucket: &[BridgeLine],
  364. config: &Config,
  365. bridges: &mut HashMap<[u8; 20], Bridge>,
  366. censor: &Censor,
  367. ) -> (HashSet<BridgeLine>, HashSet<BridgeLine>) {
  368. let mut failed = HashSet::<BridgeLine>::new();
  369. let mut succeeded = HashSet::<BridgeLine>::new();
  370. for bridgeline in bucket {
  371. if *bridgeline != BridgeLine::default() {
  372. let fingerprint = bridgeline.get_hashed_fingerprint();
  373. // Make sure bridge is in the global set
  374. if !bridges.contains_key(&fingerprint) {
  375. let bridge = Bridge::from_bridge_line(&bridgeline);
  376. bridges.insert(fingerprint, bridge);
  377. }
  378. // If this is the first time the bridge has been
  379. // distributed to a real user, store that info
  380. let bridge = bridges.get_mut(&fingerprint).unwrap();
  381. if bridge.first_real_user == 0 {
  382. bridge.first_real_user = get_date();
  383. }
  384. // Attempt to connect to the bridge
  385. if Self::connect(
  386. self.in_censorship_range,
  387. config,
  388. bridges
  389. .get_mut(&bridgeline.get_hashed_fingerprint())
  390. .unwrap(),
  391. censor,
  392. ) {
  393. self.able_to_connect = true;
  394. succeeded.insert(*bridgeline);
  395. } else {
  396. failed.insert(*bridgeline);
  397. }
  398. }
  399. }
  400. (succeeded, failed)
  401. }
  402. pub async fn get_new_credential(config: &Config) -> Result<(Lox, BridgeLine)> {
  403. get_lox_credential(
  404. &config.la_net,
  405. &get_open_invitation(&config.la_net).await?,
  406. get_lox_pub(&config.la_pubkeys),
  407. )
  408. .await
  409. }
  410. pub async fn send_negative_reports(
  411. config: &Config,
  412. reports: Vec<NegativeReport>,
  413. ) -> Result<()> {
  414. let date = get_date();
  415. let pubkey = match serde_json::from_slice::<Option<PublicKey>>(
  416. &config
  417. .tp_net
  418. .request("/nrkey".to_string(), serde_json::to_string(&date)?.into())
  419. .await?,
  420. )? {
  421. Some(v) => v,
  422. None => return Err(anyhow!("No available negative report encryption key")),
  423. };
  424. for report in reports {
  425. config
  426. .tp_net
  427. .request(
  428. "/negativereport".to_string(),
  429. bincode::serialize(&report.encrypt(&pubkey))?,
  430. )
  431. .await?;
  432. }
  433. Ok(())
  434. }
  435. pub async fn send_positive_reports(
  436. config: &Config,
  437. reports: Vec<PositiveReport>,
  438. ) -> Result<()> {
  439. for report in reports {
  440. config
  441. .tp_net
  442. .request("/positivereport".to_string(), report.to_json().into_bytes())
  443. .await?;
  444. }
  445. Ok(())
  446. }
  447. pub async fn daily_tasks(
  448. &mut self,
  449. config: &Config,
  450. bridges: &mut HashMap<[u8; 20], Bridge>,
  451. censor: &mut Censor,
  452. invites: &mut Vec<Invitation>,
  453. ) -> Result<(Vec<User>, bool)> {
  454. if self.is_censor {
  455. self.daily_tasks_censor(config, bridges, censor).await
  456. } else {
  457. match self
  458. .daily_tasks_non_censor(config, bridges, censor, invites)
  459. .await
  460. {
  461. Ok(users) => Ok((users, false)),
  462. Err(e) => Err(e),
  463. }
  464. }
  465. }
  466. // User performs daily connection attempts, etc. and returns a
  467. // vector of newly invited friends.
  468. // TODO: The map of bridges and the censor should be Arc<Mutex<>>
  469. // or something so we can parallelize this.
  470. pub async fn daily_tasks_non_censor(
  471. &mut self,
  472. config: &Config,
  473. bridges: &mut HashMap<[u8; 20], Bridge>,
  474. censor: &mut Censor,
  475. invites: &mut Vec<Invitation>,
  476. ) -> Result<Vec<User>> {
  477. // Probabilistically decide if the user should use bridges today
  478. if event_happens(self.prob_use_bridges) {
  479. self.attempted_connection = true;
  480. // Start with the assumption that we can't connect, change
  481. // only if we can
  482. self.able_to_connect = false;
  483. // Download bucket to see if bridge is still reachable. (We
  484. // assume that this step can be done even if the user can't
  485. // actually talk to the LA.)
  486. let (bucket, reachcred) = get_bucket(&config.la_net, &self.primary_cred).await?;
  487. let level = match scalar_u32(&self.primary_cred.trust_level) {
  488. Some(v) => v,
  489. None => return Err(anyhow!("Failed to get trust level from credential")),
  490. };
  491. // Can we level up the main credential?
  492. let can_level_up = level == 0
  493. && eligible_for_trust_promotion(&config.la_net, &self.primary_cred).await
  494. || reachcred.is_some()
  495. && level > 0
  496. && eligible_for_level_up(&config.la_net, &self.primary_cred).await;
  497. // Can we migrate the main credential?
  498. let can_migrate = reachcred.is_none() && level >= MIN_TRUST_LEVEL;
  499. // Can we level up the secondary credential?
  500. let mut second_level_up = false;
  501. // Track which connections succeeded and which failed. We use sets
  502. // instead of vectors for deduplication in case we test a bridge
  503. // multiple times.
  504. let mut succeeded = HashSet::<BridgeLine>::new();
  505. let mut failed = HashSet::<BridgeLine>::new();
  506. let (s, f) = self.test_bridges(&bucket, config, bridges, censor);
  507. // Add working bridges to succeeded set
  508. for b in s {
  509. succeeded.insert(b);
  510. }
  511. // Add non-working bridges to failed set
  512. for b in f {
  513. failed.insert(b);
  514. }
  515. // If we were not able to connect to any bridges but also
  516. // cannot migrate, ask for a new invitation
  517. if !self.able_to_connect && !can_migrate {
  518. while let Some(invite) = invites.pop() {
  519. match redeem_invite(
  520. &config.la_net,
  521. &invite,
  522. get_lox_pub(&config.la_pubkeys),
  523. get_invitation_pub(&config.la_pubkeys),
  524. )
  525. .await
  526. {
  527. Ok((cred, bucket)) => {
  528. self.primary_cred = cred;
  529. // Test our bridges
  530. let (s, f) = self.test_bridges(&bucket, config, bridges, censor);
  531. for b in s {
  532. succeeded.insert(b);
  533. }
  534. for b in f {
  535. failed.insert(b);
  536. }
  537. // We got a credential. Stop now.
  538. break;
  539. }
  540. Err(e) => {
  541. println!("Failed to redeem invite. Error: {}", e);
  542. }
  543. }
  544. }
  545. }
  546. // If we were still not able to connect to any bridges, get
  547. // a second credential
  548. let second_cred = if !self.able_to_connect {
  549. if self.secondary_cred.is_some() {
  550. std::mem::replace(&mut self.secondary_cred, None)
  551. } else {
  552. // If the censor is in play, we cannot get open-entry invites
  553. if censor.is_active() {
  554. None
  555. } else {
  556. // Get new credential
  557. match Self::get_new_credential(&config).await {
  558. Ok((cred, _bl)) => Some(cred),
  559. Err(e) => {
  560. eprintln!("Failed to get new Lox credential. Error: {}", e);
  561. None
  562. }
  563. }
  564. }
  565. }
  566. } else {
  567. // If we're able to connect with the primary credential, don't
  568. // keep a secondary one.
  569. None
  570. };
  571. if second_cred.is_some() {
  572. let second_cred = second_cred.as_ref().unwrap();
  573. // Test our bridges
  574. let (second_bucket, second_reachcred) =
  575. get_bucket(&config.la_net, &second_cred).await?;
  576. let (s, f) = self.test_bridges(&second_bucket, config, bridges, censor);
  577. // Add each working bridge to succeeded set
  578. for b in s {
  579. succeeded.insert(b);
  580. }
  581. // Add each non-working bridge to failed set
  582. for b in f {
  583. failed.insert(b);
  584. }
  585. // If we're able to connect, see if we can level up
  586. if self.able_to_connect {
  587. if second_reachcred.is_some()
  588. && eligible_for_trust_promotion(&config.la_net, &second_cred).await
  589. {
  590. second_level_up = true;
  591. }
  592. }
  593. }
  594. let mut negative_reports = Vec::<NegativeReport>::new();
  595. let mut positive_reports = Vec::<PositiveReport>::new();
  596. if self.submits_reports {
  597. for bridgeline in &failed {
  598. negative_reports.push(NegativeReport::from_bridgeline(
  599. *bridgeline,
  600. config.country.to_string(),
  601. BridgeDistributor::Lox,
  602. ));
  603. }
  604. if level >= 3 {
  605. for bridgeline in &succeeded {
  606. // If we haven't received a positive report yet,
  607. // add a record about it with today's date
  608. let fingerprint = bridgeline.get_hashed_fingerprint();
  609. let bridge = bridges.get_mut(&fingerprint).unwrap();
  610. if bridge.first_positive_report == 0 {
  611. bridge.first_positive_report = get_date();
  612. }
  613. if let Ok(pr) = PositiveReport::from_lox_credential(
  614. fingerprint,
  615. None,
  616. &self.primary_cred,
  617. get_lox_pub(&config.la_pubkeys),
  618. config.country.to_string(),
  619. ) {
  620. positive_reports.push(pr)
  621. }
  622. }
  623. }
  624. }
  625. // We might restrict these steps to succeeded.len() > 0, but
  626. // we do assume the user can contact the LA somehow, so
  627. // let's just allow it.
  628. if can_level_up {
  629. // Trust migration from level 0 to level 1
  630. let cred = if level == 0 {
  631. trust_migration(
  632. &config.la_net,
  633. &self.primary_cred,
  634. &trust_promotion(
  635. &config.la_net,
  636. &self.primary_cred,
  637. get_lox_pub(&config.la_pubkeys),
  638. )
  639. .await?,
  640. get_lox_pub(&config.la_pubkeys),
  641. get_migration_pub(&config.la_pubkeys),
  642. )
  643. .await?
  644. } else {
  645. // Level up from level 1+
  646. level_up(
  647. &config.la_net,
  648. &self.primary_cred,
  649. &reachcred.unwrap(), // must be Some
  650. get_lox_pub(&config.la_pubkeys),
  651. get_reachability_pub(&config.la_pubkeys),
  652. )
  653. .await?
  654. };
  655. self.primary_cred = cred;
  656. self.secondary_cred = None;
  657. } else if can_migrate {
  658. // If we can't level up, try to migrate
  659. let cred = blockage_migration(
  660. &config.la_net,
  661. &self.primary_cred,
  662. &check_blockage(
  663. &config.la_net,
  664. &self.primary_cred,
  665. get_lox_pub(&config.la_pubkeys),
  666. )
  667. .await?,
  668. get_lox_pub(&config.la_pubkeys),
  669. get_migration_pub(&config.la_pubkeys),
  670. )
  671. .await?;
  672. self.primary_cred = cred;
  673. self.secondary_cred = None;
  674. } else if second_level_up {
  675. // If we can't migrate, try to level up our secondary
  676. // credential
  677. let second_cred = second_cred.as_ref().unwrap();
  678. let cred = trust_migration(
  679. &config.la_net,
  680. &second_cred,
  681. &trust_promotion(
  682. &config.la_net,
  683. &second_cred,
  684. get_lox_pub(&config.la_pubkeys),
  685. )
  686. .await?,
  687. get_lox_pub(&config.la_pubkeys),
  688. get_migration_pub(&config.la_pubkeys),
  689. )
  690. .await?;
  691. self.primary_cred = cred;
  692. self.secondary_cred = None;
  693. } else if second_cred.is_some() {
  694. // Couldn't connect with primary credential
  695. if self.able_to_connect {
  696. // Keep the second credential only if it's useful
  697. self.secondary_cred = second_cred;
  698. }
  699. }
  700. if !negative_reports.is_empty() {
  701. Self::send_negative_reports(&config, negative_reports).await?;
  702. }
  703. if !positive_reports.is_empty() {
  704. Self::send_positive_reports(&config, positive_reports).await?;
  705. }
  706. // Invite friends if applicable
  707. let invitations = match scalar_u32(&self.primary_cred.invites_remaining) {
  708. Some(v) => v,
  709. None => 0, // This is probably an error case that should not happen
  710. };
  711. // It's just more convenient in the code to do this this way.
  712. // Invite censors directly as new users. If the invited user is
  713. // not a censor, instead add the invitation to a global list.
  714. let mut new_censors = Vec::<User>::new();
  715. // Scale the probability of inviting a censor, based on the
  716. // user's own trust level. We assume that users with
  717. // more-trusted credentials are less likely to invite
  718. // censors because they have more to lose.
  719. let level_scale = match scalar_u32(&self.primary_cred.trust_level) {
  720. // These numbers are fairly arbitrary.
  721. Some(4) => 0.25,
  722. Some(3) => 0.5,
  723. Some(2) => 1.0,
  724. _ => 1.0, // should not have invitations
  725. };
  726. for _ in 0..invitations {
  727. if event_happens(config.prob_user_invites_friend) {
  728. match self.get_invite(config, bridges, censor).await {
  729. Ok(invite) => {
  730. // With some probability, the user is convinced to
  731. // invite a censor. We assume users with higher
  732. // trust levels will be more cautious with
  733. // invitations because they have more to lose.
  734. if censor.is_active()
  735. && event_happens(config.prob_censor_gets_invite * level_scale)
  736. {
  737. // Invite friend (who might be a censor)
  738. match Self::from_invite(invite, config, true, bridges, censor).await
  739. {
  740. Ok(friend) => {
  741. // You really shouldn't push your friends,
  742. // especially new ones whose boundaries you
  743. // might not know well.
  744. new_censors.push(friend);
  745. }
  746. Err(e) => {
  747. println!("{}", e);
  748. }
  749. }
  750. } else {
  751. invites.push(invite);
  752. }
  753. }
  754. Err(e) => {
  755. println!("{}", e);
  756. }
  757. }
  758. }
  759. }
  760. Ok(new_censors)
  761. } else {
  762. // If we didn't try to connect, indicate so. This is to
  763. // prevent users from being counted as able/unable to
  764. // connect when they just haven't tried.
  765. self.attempted_connection = false;
  766. Ok(Vec::<User>::new())
  767. }
  768. }
  769. // User cooperates with censor and performs daily tasks to try to
  770. // learn more bridges. Returns a vector of newly invited users
  771. // and a boolean indicating whether this censor user should be
  772. // removed from the global user set (for efficiency).
  773. pub async fn daily_tasks_censor(
  774. &mut self,
  775. config: &Config,
  776. bridges: &mut HashMap<[u8; 20], Bridge>,
  777. censor: &mut Censor,
  778. ) -> Result<(Vec<User>, bool)> {
  779. // Download bucket to see if bridge is still reachable and if we
  780. // have any new bridges
  781. let (bucket, reachcred) = get_bucket(&config.la_net, &self.primary_cred).await?;
  782. let level = scalar_u32(&self.primary_cred.trust_level).unwrap();
  783. // Make sure each bridge is in global bridges set and known by
  784. // censor
  785. give_bucket_to_censor(&bucket, bridges, censor);
  786. // If Lox has marked the bridge blocked, migrate if possible
  787. if bucket_blocked_lox(&bucket, bridges) {
  788. // If we can migrate, migrate
  789. if level >= MIN_TRUST_LEVEL {
  790. if let Ok(migcred) = check_blockage(
  791. &config.la_net,
  792. &self.primary_cred,
  793. get_lox_pub(&config.la_pubkeys),
  794. )
  795. .await
  796. {
  797. if let Ok(cred) = blockage_migration(
  798. &config.la_net,
  799. &self.primary_cred,
  800. &migcred,
  801. get_lox_pub(&config.la_pubkeys),
  802. get_migration_pub(&config.la_pubkeys),
  803. )
  804. .await
  805. {
  806. // Successfully migrated!
  807. // Update credential
  808. self.primary_cred = cred;
  809. // You can't migrate to level 3 or 4, so the
  810. // censor doesn't want this new credential
  811. // Download bucket to see if bridge is still
  812. // reachable and if we have any new bridges
  813. let (bucket, _reachcred) =
  814. get_bucket(&config.la_net, &self.primary_cred).await?;
  815. // Give new bucket to censor
  816. give_bucket_to_censor(&bucket, bridges, censor);
  817. // Add this user to censor's list
  818. censor.add_agent(&self.primary_cred.bucket);
  819. }
  820. }
  821. } else {
  822. // We can't migrate, and we can't level up or anything.
  823. // Mark this user for deletion.
  824. return Ok((Vec::<User>::new(), true));
  825. }
  826. }
  827. // Censor user tries to level up their primary credential
  828. if level == 0 && eligible_for_trust_promotion(&config.la_net, &self.primary_cred).await
  829. || reachcred.is_some()
  830. && level > 0
  831. && eligible_for_level_up(&config.la_net, &self.primary_cred).await
  832. {
  833. let new_cred = if level == 0 {
  834. let nc = trust_migration(
  835. &config.la_net,
  836. &self.primary_cred,
  837. &trust_promotion(
  838. &config.la_net,
  839. &self.primary_cred,
  840. get_lox_pub(&config.la_pubkeys),
  841. )
  842. .await?,
  843. get_lox_pub(&config.la_pubkeys),
  844. get_migration_pub(&config.la_pubkeys),
  845. )
  846. .await?;
  847. // We now have a new bucket value, so add the user to censor's list
  848. censor.add_agent(&nc.bucket);
  849. // New credential as new_cred
  850. nc
  851. } else {
  852. level_up(
  853. &config.la_net,
  854. &self.primary_cred,
  855. &reachcred.unwrap(), // must be Some
  856. get_lox_pub(&config.la_pubkeys),
  857. get_reachability_pub(&config.la_pubkeys),
  858. )
  859. .await?
  860. };
  861. self.primary_cred = new_cred;
  862. let (bucket, _reachcred) = get_bucket(&config.la_net, &self.primary_cred).await?;
  863. // Make sure each bridge is in global bridges set and
  864. // known by censor
  865. for bl in bucket {
  866. let fingerprint = bl.get_hashed_fingerprint();
  867. if !bridges.contains_key(&fingerprint) {
  868. let bridge = Bridge::from_bridge_line(&bl);
  869. bridges.insert(fingerprint, bridge);
  870. }
  871. censor.learn_bridge(&fingerprint);
  872. if level == 2 {
  873. // level up to 3
  874. // Give censor an additional credential
  875. censor.give_lox_cred(&fingerprint, &self.primary_cred, true);
  876. } else if level > 2 {
  877. // level up to 4
  878. // Replace censor's credential with newer one,
  879. // but don't add to count of censor's
  880. // credentials
  881. censor.give_lox_cred(&fingerprint, &self.primary_cred, false);
  882. }
  883. }
  884. }
  885. // Censor user invites as many censor friends as possible
  886. let invitations = scalar_u32(&self.primary_cred.invites_remaining).unwrap();
  887. let mut new_friends = Vec::<User>::new();
  888. for _ in 0..invitations {
  889. match self.get_invite(config, bridges, censor).await {
  890. Ok(invite) => {
  891. match Self::from_invite(invite, &config, true, bridges, censor).await {
  892. Ok(friend) => {
  893. new_friends.push(friend);
  894. }
  895. Err(e) => {
  896. println!("{}", e);
  897. }
  898. }
  899. }
  900. Err(e) => {
  901. println!("{}", e);
  902. }
  903. }
  904. }
  905. Ok((new_friends, false))
  906. }
  907. }