user.rs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. // User behavior in simulation
  2. use crate::{
  3. get_date,
  4. negative_report::NegativeReport,
  5. positive_report::PositiveReport,
  6. simulation::{
  7. bridge::Bridge,
  8. censor::{Censor, Secrecy::*, Totality::*},
  9. config::Config,
  10. },
  11. BridgeDistributor,
  12. };
  13. use anyhow::{anyhow, Result};
  14. use lox_cli::{networking::*, *};
  15. use lox_library::{
  16. bridge_table::BridgeLine, cred::Lox, proto::check_blockage::MIN_TRUST_LEVEL, scalar_u32,
  17. };
  18. use rand::Rng;
  19. use std::{cmp::min, collections::HashMap};
  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. pub struct User {
  28. // Does this user cooperate with a censor?
  29. pub is_censor: bool,
  30. // The user always has a primary credential. If this credential's bucket is
  31. // blocked, the user may replace it or temporarily hold two credentials
  32. // while waiting to migrate from the primary credential.
  33. pub primary_cred: Lox,
  34. secondary_cred: Option<Lox>,
  35. // Does the user submit reports to Troll Patrol?
  36. submits_reports: bool,
  37. // How likely is this user to use bridges on a given day?
  38. prob_use_bridges: f64,
  39. }
  40. impl User {
  41. pub async fn new(config: &Config, is_censor: bool) -> Result<Self> {
  42. let cred = get_lox_credential(
  43. &config.la_net,
  44. &get_open_invitation(&config.la_net).await?,
  45. get_lox_pub(&config.la_pubkeys),
  46. )
  47. .await?
  48. .0;
  49. // Probabilistically decide whether this user submits reports
  50. let submits_reports = if is_censor {
  51. false
  52. } else {
  53. event_happens(config.prob_user_submits_reports)
  54. };
  55. // Randomly determine how likely this user is to use bridges on
  56. // a given day
  57. let mut rng = rand::thread_rng();
  58. let prob_use_bridges = rng.gen_range(0.0..=1.0);
  59. Ok(Self {
  60. is_censor,
  61. primary_cred: cred,
  62. secondary_cred: None,
  63. submits_reports: submits_reports,
  64. prob_use_bridges: prob_use_bridges,
  65. })
  66. }
  67. pub async fn trusted_user(config: &Config) -> Result<Self> {
  68. let cred = get_lox_credential(
  69. &config.la_net,
  70. &get_open_invitation(&config.la_net).await?,
  71. get_lox_pub(&config.la_pubkeys),
  72. )
  73. .await?
  74. .0;
  75. Ok(Self {
  76. is_censor: false,
  77. primary_cred: cred,
  78. secondary_cred: None,
  79. submits_reports: true,
  80. prob_use_bridges: 1.0,
  81. })
  82. }
  83. // TODO: This should probably return an actual error type
  84. pub async fn invite(
  85. &mut self,
  86. config: &Config,
  87. censor: &mut Censor,
  88. invited_user_is_censor: bool,
  89. ) -> Result<Self> {
  90. let etable = get_reachability_credential(&config.la_net).await?;
  91. let (new_cred, invite) = issue_invite(
  92. &config.la_net,
  93. &self.primary_cred,
  94. &etable,
  95. get_lox_pub(&config.la_pubkeys),
  96. get_reachability_pub(&config.la_pubkeys),
  97. get_invitation_pub(&config.la_pubkeys),
  98. )
  99. .await?;
  100. self.primary_cred = new_cred;
  101. if self.is_censor {
  102. // Make sure censor has access to each bridge and each
  103. // credential
  104. let (bucket, _reachcred) = get_bucket(&config.la_net, &self.primary_cred).await?;
  105. for bl in bucket {
  106. let fingerprint = bl.get_hashed_fingerprint();
  107. censor.learn_bridge(&fingerprint);
  108. censor.give_lox_cred(&fingerprint, &self.primary_cred);
  109. }
  110. }
  111. let friend_cred = redeem_invite(
  112. &config.la_net,
  113. &invite,
  114. get_lox_pub(&config.la_pubkeys),
  115. get_invitation_pub(&config.la_pubkeys),
  116. )
  117. .await?
  118. .0;
  119. // Calling function decides if the invited user is a censor
  120. let is_censor = invited_user_is_censor;
  121. // Probabilistically decide whether this user submits reports
  122. let submits_reports = if is_censor {
  123. false
  124. } else {
  125. event_happens(config.prob_user_submits_reports)
  126. };
  127. // Randomly determine how likely this user is to use bridges on
  128. // a given day
  129. let mut rng = rand::thread_rng();
  130. let prob_use_bridges = rng.gen_range(0.0..=1.0);
  131. Ok(Self {
  132. is_censor,
  133. primary_cred: friend_cred,
  134. secondary_cred: None,
  135. submits_reports: submits_reports,
  136. prob_use_bridges: prob_use_bridges,
  137. })
  138. }
  139. // Attempt to "connect" to the bridge, returns true if successful.
  140. // Note that this does not involve making a real connection to a
  141. // real bridge. The function is async because the *censor* might
  142. // submit a positive report during this function.
  143. pub fn connect(&self, config: &Config, bridge: &mut Bridge, censor: &Censor) -> bool {
  144. if censor.blocks_bridge(config, &bridge.fingerprint) {
  145. if config.censor_totality == Full
  146. || config.censor_totality == Partial
  147. && event_happens(censor.partial_blocking_percent)
  148. {
  149. // If censor tries to hide its censorship, record a
  150. // false connection
  151. if config.censor_secrecy == Hiding {
  152. bridge.connect_total();
  153. }
  154. // Return false because the connection failed
  155. return false;
  156. } else if config.censor_totality == Throttling {
  157. // With some probability, the user connects but gives up
  158. // because there is too much interference. In this case,
  159. // a real connection occurs, but we treat it like a
  160. // false connection from the censor.
  161. if event_happens(config.prob_user_treats_throttling_as_blocking) {
  162. bridge.connect_total();
  163. // Return false because there was interference
  164. // detected in the connection
  165. return false;
  166. }
  167. }
  168. }
  169. // Connection may randomly fail, without censor intervention
  170. if event_happens(config.prob_connection_fails) {
  171. return false;
  172. }
  173. // If we haven't returned yet, the connection succeeded
  174. bridge.connect_real();
  175. true
  176. }
  177. pub async fn get_new_credential(config: &Config) -> Result<(Lox, BridgeLine)> {
  178. get_lox_credential(
  179. &config.la_net,
  180. &get_open_invitation(&config.la_net).await?,
  181. get_lox_pub(&config.la_pubkeys),
  182. )
  183. .await
  184. }
  185. pub async fn send_negative_reports(
  186. config: &Config,
  187. reports: Vec<NegativeReport>,
  188. ) -> Result<()> {
  189. let date = get_date();
  190. let pubkey = match serde_json::from_slice::<Option<PublicKey>>(
  191. &config
  192. .tp_net
  193. .request("/nrkey".to_string(), serde_json::to_string(&date)?.into())
  194. .await?,
  195. )? {
  196. Some(v) => v,
  197. None => return Err(anyhow!("No available negative report encryption key")),
  198. };
  199. for report in reports {
  200. config
  201. .tp_net
  202. .request(
  203. "/negativereport".to_string(),
  204. bincode::serialize(&report.encrypt(&pubkey))?,
  205. )
  206. .await?;
  207. }
  208. Ok(())
  209. }
  210. pub async fn send_positive_reports(
  211. config: &Config,
  212. reports: Vec<PositiveReport>,
  213. ) -> Result<()> {
  214. for report in reports {
  215. config
  216. .tp_net
  217. .request("/positivereport".to_string(), report.to_json().into_bytes())
  218. .await?;
  219. }
  220. Ok(())
  221. }
  222. pub async fn daily_tasks(
  223. &mut self,
  224. config: &Config,
  225. num_users_requesting_invites: u32,
  226. num_censor_invites: u32,
  227. bridges: &mut HashMap<[u8; 20], Bridge>,
  228. censor: &mut Censor,
  229. ) -> Result<Vec<User>> {
  230. if self.is_censor {
  231. self.daily_tasks_censor(config, bridges, censor).await
  232. } else {
  233. self.daily_tasks_non_censor(
  234. config,
  235. num_users_requesting_invites,
  236. num_censor_invites,
  237. bridges,
  238. censor,
  239. )
  240. .await
  241. }
  242. }
  243. // User performs daily connection attempts, etc. and returns a
  244. // vector of newly invited friends.
  245. // TODO: The map of bridges and the censor should be Arc<Mutex<>>
  246. // or something so we can parallelize this.
  247. pub async fn daily_tasks_non_censor(
  248. &mut self,
  249. config: &Config,
  250. num_users_requesting_invites: u32,
  251. num_censor_invites: u32,
  252. bridges: &mut HashMap<[u8; 20], Bridge>,
  253. censor: &mut Censor,
  254. ) -> Result<Vec<User>> {
  255. // Probabilistically decide if the user should use bridges today
  256. if event_happens(self.prob_use_bridges) {
  257. // Download bucket to see if bridge is still reachable. (We
  258. // assume that this step can be done even if the user can't
  259. // actually talk to the LA.)
  260. let (bucket, reachcred) = get_bucket(&config.la_net, &self.primary_cred).await?;
  261. let level = match scalar_u32(&self.primary_cred.trust_level) {
  262. Some(v) => v,
  263. None => return Err(anyhow!("Failed to get trust level from credential")),
  264. };
  265. // Make sure each bridge in bucket is in the global bridges set
  266. for bridgeline in bucket {
  267. if bridgeline != BridgeLine::default() {
  268. if !bridges.contains_key(&bridgeline.get_hashed_fingerprint()) {
  269. let bridge = Bridge::from_bridge_line(&bridgeline);
  270. bridges.insert(bridgeline.get_hashed_fingerprint(), bridge);
  271. }
  272. }
  273. }
  274. // Can we level up the main credential?
  275. let can_level_up = reachcred.is_some()
  276. && (level == 0
  277. && eligible_for_trust_promotion(&config.la_net, &self.primary_cred).await
  278. || level > 0
  279. && eligible_for_level_up(&config.la_net, &self.primary_cred).await);
  280. // Can we migrate the main credential?
  281. let can_migrate = reachcred.is_none() && level >= MIN_TRUST_LEVEL;
  282. // Can we level up the secondary credential?
  283. let mut second_level_up = false;
  284. let mut failed = Vec::<BridgeLine>::new();
  285. let mut succeeded = Vec::<BridgeLine>::new();
  286. // Try to connect to each bridge
  287. for i in 0..bucket.len() {
  288. // At level 0, we only have 1 bridge
  289. if bucket[i] != BridgeLine::default() {
  290. if self.connect(
  291. &config,
  292. bridges
  293. .get_mut(&bucket[i].get_hashed_fingerprint())
  294. .unwrap(),
  295. &censor,
  296. ) {
  297. succeeded.push(bucket[i]);
  298. } else {
  299. failed.push(bucket[i]);
  300. }
  301. }
  302. }
  303. // If we were not able to connect to any bridges, get a
  304. // second credential
  305. let second_cred = if succeeded.len() < 1 {
  306. if self.secondary_cred.is_some() {
  307. std::mem::replace(&mut self.secondary_cred, None)
  308. } else {
  309. // Get new credential
  310. match Self::get_new_credential(&config).await {
  311. Ok((cred, _bl)) => Some(cred),
  312. Err(e) => {
  313. eprintln!("Failed to get new Lox credential. Error: {}", e);
  314. None
  315. }
  316. }
  317. }
  318. } else {
  319. // If we're able to connect with the primary credential, don't
  320. // keep a secondary one.
  321. None
  322. };
  323. if second_cred.is_some() {
  324. let second_cred = second_cred.as_ref().unwrap();
  325. let (second_bucket, second_reachcred) =
  326. get_bucket(&config.la_net, &second_cred).await?;
  327. for bridgeline in second_bucket {
  328. if bridgeline != BridgeLine::default() {
  329. if !bridges.contains_key(&bridgeline.get_hashed_fingerprint()) {
  330. bridges.insert(
  331. bridgeline.get_hashed_fingerprint(),
  332. Bridge::from_bridge_line(&bridgeline),
  333. );
  334. }
  335. // Attempt to connect to second cred's bridge
  336. if self.connect(
  337. &config,
  338. bridges
  339. .get_mut(&bridgeline.get_hashed_fingerprint())
  340. .unwrap(),
  341. censor,
  342. ) {
  343. succeeded.push(bridgeline);
  344. if second_reachcred.is_some()
  345. && eligible_for_trust_promotion(&config.la_net, &second_cred).await
  346. {
  347. second_level_up = true;
  348. }
  349. } else {
  350. failed.push(bridgeline);
  351. }
  352. }
  353. }
  354. }
  355. let mut negative_reports = Vec::<NegativeReport>::new();
  356. let mut positive_reports = Vec::<PositiveReport>::new();
  357. if self.submits_reports {
  358. for bridgeline in &failed {
  359. negative_reports.push(NegativeReport::from_bridgeline(
  360. *bridgeline,
  361. config.country.to_string(),
  362. BridgeDistributor::Lox,
  363. ));
  364. }
  365. if level >= 3 {
  366. for bridgeline in &succeeded {
  367. // If we haven't received a positive report yet,
  368. // add a record about it with today's date
  369. let bridge = bridges
  370. .get_mut(&bridgeline.get_hashed_fingerprint())
  371. .unwrap();
  372. if bridge.first_positive_report == 0 {
  373. bridge.first_positive_report = get_date();
  374. }
  375. positive_reports.push(
  376. PositiveReport::from_lox_credential(
  377. bridgeline.get_hashed_fingerprint(),
  378. None,
  379. &self.primary_cred,
  380. get_lox_pub(&config.la_pubkeys),
  381. config.country.to_string(),
  382. )
  383. .unwrap(),
  384. );
  385. }
  386. }
  387. }
  388. // We might restrict these steps to succeeded.len() > 0, but
  389. // we do assume the user can contact the LA somehow, so
  390. // let's just allow it.
  391. if can_level_up {
  392. let cred = if level == 0 {
  393. trust_migration(
  394. &config.la_net,
  395. &self.primary_cred,
  396. &trust_promotion(
  397. &config.la_net,
  398. &self.primary_cred,
  399. get_lox_pub(&config.la_pubkeys),
  400. )
  401. .await?,
  402. get_lox_pub(&config.la_pubkeys),
  403. get_migration_pub(&config.la_pubkeys),
  404. )
  405. .await?
  406. } else {
  407. level_up(
  408. &config.la_net,
  409. &self.primary_cred,
  410. &reachcred.unwrap(),
  411. get_lox_pub(&config.la_pubkeys),
  412. get_reachability_pub(&config.la_pubkeys),
  413. )
  414. .await?
  415. };
  416. self.primary_cred = cred;
  417. self.secondary_cred = None;
  418. }
  419. // We favor starting over at level 1 to migrating to level
  420. // 1, but if we have a level 4 credential for a bridge that
  421. // hasn't been marked blocked, save the credential so we can
  422. // migrate to a level 2 cred. Note that second_level_up is
  423. // only true if we were unable to connect with bridges from
  424. // our primary credential.
  425. else if second_level_up && (level <= MIN_TRUST_LEVEL || reachcred.is_none()) {
  426. let second_cred = second_cred.as_ref().unwrap();
  427. let cred = trust_migration(
  428. &config.la_net,
  429. &second_cred,
  430. &trust_promotion(
  431. &config.la_net,
  432. &second_cred,
  433. get_lox_pub(&config.la_pubkeys),
  434. )
  435. .await?,
  436. get_lox_pub(&config.la_pubkeys),
  437. get_migration_pub(&config.la_pubkeys),
  438. )
  439. .await?;
  440. self.primary_cred = cred;
  441. self.secondary_cred = None;
  442. } else if can_migrate {
  443. let cred = blockage_migration(
  444. &config.la_net,
  445. &self.primary_cred,
  446. &check_blockage(
  447. &config.la_net,
  448. &self.primary_cred,
  449. get_lox_pub(&config.la_pubkeys),
  450. )
  451. .await?,
  452. get_lox_pub(&config.la_pubkeys),
  453. get_migration_pub(&config.la_pubkeys),
  454. )
  455. .await?;
  456. self.primary_cred = cred;
  457. self.secondary_cred = None;
  458. } else if second_cred.is_some() {
  459. // Couldn't connect with primary credential
  460. if succeeded.len() > 0 {
  461. // Keep the second credential only if it's useful
  462. self.secondary_cred = second_cred;
  463. }
  464. }
  465. if negative_reports.len() > 0 {
  466. Self::send_negative_reports(&config, negative_reports).await?;
  467. }
  468. if positive_reports.len() > 0 {
  469. Self::send_positive_reports(&config, positive_reports).await?;
  470. }
  471. // Invite friends if applicable
  472. let invitations = match scalar_u32(&self.primary_cred.invites_remaining) {
  473. Some(v) => v,
  474. None => 0, // This is probably an error case that should not happen
  475. };
  476. let mut new_friends = Vec::<User>::new();
  477. for _i in 0..min(invitations, num_users_requesting_invites) {
  478. if event_happens(config.prob_user_invites_friend) {
  479. // Invite non-censor friend
  480. match self.invite(&config, censor, false).await {
  481. Ok(friend) => {
  482. // You really shouldn't push your friends,
  483. // especially new ones whose boundaries you
  484. // might not know well.
  485. new_friends.push(friend);
  486. }
  487. Err(e) => {
  488. println!("{}", e);
  489. }
  490. }
  491. }
  492. }
  493. // Invite censor users if applicable
  494. let invitations = invitations - new_friends.len() as u32;
  495. for _i in 0..min(invitations, num_censor_invites) {
  496. if event_happens(config.prob_user_invites_friend) {
  497. // Invite non-censor friend
  498. match self.invite(&config, censor, true).await {
  499. Ok(friend) => {
  500. new_friends.push(friend);
  501. }
  502. Err(e) => {
  503. println!("{}", e);
  504. }
  505. }
  506. }
  507. }
  508. Ok(new_friends)
  509. } else {
  510. Ok(Vec::<User>::new())
  511. }
  512. }
  513. // User cooperates with censor and performs daily tasks to try to
  514. // learn more bridges.
  515. pub async fn daily_tasks_censor(
  516. &mut self,
  517. config: &Config,
  518. bridges: &mut HashMap<[u8; 20], Bridge>,
  519. censor: &mut Censor,
  520. ) -> Result<Vec<User>> {
  521. // Download bucket to see if bridge is still reachable and if we
  522. // have any new bridges
  523. let (bucket, reachcred) = get_bucket(&config.la_net, &self.primary_cred).await?;
  524. let level = scalar_u32(&self.primary_cred.trust_level).unwrap();
  525. // Make sure each bridge is in global bridges set and known by
  526. // censor
  527. for bridgeline in bucket {
  528. if bridgeline != BridgeLine::default() {
  529. if !bridges.contains_key(&bridgeline.get_hashed_fingerprint()) {
  530. let bridge = Bridge::from_bridge_line(&bridgeline);
  531. bridges.insert(bridgeline.get_hashed_fingerprint(), bridge);
  532. }
  533. censor.learn_bridge(&bridgeline.get_hashed_fingerprint());
  534. }
  535. }
  536. // Censor user tries to level up their primary credential
  537. if reachcred.is_some() {
  538. if level == 0 && eligible_for_trust_promotion(&config.la_net, &self.primary_cred).await
  539. || level > 0 && eligible_for_level_up(&config.la_net, &self.primary_cred).await
  540. {
  541. let new_cred = if level == 0 {
  542. trust_migration(
  543. &config.la_net,
  544. &self.primary_cred,
  545. &trust_promotion(
  546. &config.la_net,
  547. &self.primary_cred,
  548. get_lox_pub(&config.la_pubkeys),
  549. )
  550. .await?,
  551. get_lox_pub(&config.la_pubkeys),
  552. get_migration_pub(&config.la_pubkeys),
  553. )
  554. .await?
  555. } else {
  556. level_up(
  557. &config.la_net,
  558. &self.primary_cred,
  559. &reachcred.unwrap(),
  560. get_lox_pub(&config.la_pubkeys),
  561. get_reachability_pub(&config.la_pubkeys),
  562. )
  563. .await?
  564. };
  565. self.primary_cred = new_cred;
  566. let (bucket, _reachcred) = get_bucket(&config.la_net, &self.primary_cred).await?;
  567. // Make sure each bridge is in global bridges set and
  568. // known by censor
  569. for bl in bucket {
  570. let fingerprint = bl.get_hashed_fingerprint();
  571. if !bridges.contains_key(&fingerprint) {
  572. let bridge = Bridge::from_bridge_line(&bl);
  573. bridges.insert(fingerprint, bridge);
  574. }
  575. censor.learn_bridge(&fingerprint);
  576. censor.give_lox_cred(&fingerprint, &self.primary_cred);
  577. }
  578. }
  579. } else {
  580. // LA has identified this bucket as blocked. This change
  581. // will not be reverted, so replace the primary credential
  582. // with a new level 0 credential and work on gaining trust
  583. // for that one.
  584. let res = Self::get_new_credential(&config).await;
  585. if res.is_ok() {
  586. let (new_cred, bl) = res.unwrap();
  587. let fingerprint = bl.get_hashed_fingerprint();
  588. if !bridges.contains_key(&fingerprint) {
  589. let bridge = Bridge::from_bridge_line(&bl);
  590. bridges.insert(fingerprint, bridge);
  591. }
  592. censor.learn_bridge(&fingerprint);
  593. // Censor doesn't want new_cred yet
  594. self.primary_cred = new_cred;
  595. } else {
  596. eprintln!("Censor failed to get new credential");
  597. }
  598. }
  599. // Separately from primary credential, censor user requests a
  600. // new secondary credential each day just to block the
  601. // open-entry bridges. This is stored but not reused.
  602. let res = Self::get_new_credential(&config).await;
  603. if res.is_ok() {
  604. let (_new_cred, bl) = res.unwrap();
  605. let fingerprint = bl.get_hashed_fingerprint();
  606. if !bridges.contains_key(&fingerprint) {
  607. let bridge = Bridge::from_bridge_line(&bl);
  608. bridges.insert(fingerprint, bridge);
  609. }
  610. censor.learn_bridge(&fingerprint);
  611. // Censor doesn't want new_cred. User doesn't actually use
  612. // secondary_cred, so don't store it.
  613. } else {
  614. eprintln!("Censor failed to get new credential");
  615. }
  616. // Censor user invites as many censor friends as possible
  617. let invitations = scalar_u32(&self.primary_cred.invites_remaining).unwrap();
  618. let mut new_friends = Vec::<User>::new();
  619. for _ in 0..invitations {
  620. match self.invite(&config, censor, true).await {
  621. Ok(friend) => {
  622. new_friends.push(friend);
  623. }
  624. Err(e) => {
  625. println!("{}", e);
  626. }
  627. }
  628. }
  629. Ok(new_friends)
  630. }
  631. }