lib.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. use std::convert::TryInto;
  2. use rand::{thread_rng, SeedableRng, RngCore};
  3. use rand_chacha::ChaCha20Rng;
  4. use spiral_rs::{client::*, discrete_gaussian::*, util::*};
  5. use wasm_bindgen::prelude::*;
  6. const UUID_V4_LEN: usize = 36;
  7. // console_log! macro
  8. #[wasm_bindgen]
  9. extern "C" {
  10. #[wasm_bindgen(js_namespace = console)]
  11. fn log(s: &str);
  12. }
  13. #[allow(unused_macros)]
  14. macro_rules! console_log {
  15. ($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
  16. }
  17. // Container class for a static lifetime Client
  18. // Avoids a lifetime in the return signature of bound Rust functions
  19. #[wasm_bindgen]
  20. pub struct WrappedClient {
  21. client: &'static mut Client<'static, ChaCha20Rng>,
  22. }
  23. // Very simply test to ensure random generation is not obviously biased.
  24. fn _dg_seems_okay() {
  25. let params = get_test_params();
  26. let mut rng = thread_rng();
  27. let mut dg = DiscreteGaussian::init(&params, &mut rng);
  28. let mut v = Vec::new();
  29. let trials = 10000;
  30. let mut sum = 0;
  31. for _ in 0..trials {
  32. let val = dg.sample();
  33. v.push(val);
  34. sum += val;
  35. }
  36. let mean = sum as f64 / trials as f64;
  37. let std_dev = params.noise_width / f64::sqrt(2f64 * std::f64::consts::PI);
  38. let std_dev_of_mean = std_dev / f64::sqrt(trials as f64);
  39. assert!(f64::abs(mean) < std_dev_of_mean * 5f64);
  40. }
  41. // Initializes a client; can optionally take in a set of parameters
  42. #[wasm_bindgen]
  43. pub fn initialize(json_params: Option<String>, seed: Box<[u8]>) -> WrappedClient {
  44. // spiral_rs::ntt::test::ntt_correct();
  45. let cfg = r#"
  46. {'n': 2,
  47. 'nu_1': 10,
  48. 'nu_2': 6,
  49. 'p': 512,
  50. 'q2_bits': 21,
  51. 's_e': 85.83255142749422,
  52. 't_gsw': 10,
  53. 't_conv': 4,
  54. 't_exp_left': 16,
  55. 't_exp_right': 56,
  56. 'instances': 11,
  57. 'db_item_size': 100000 }
  58. "#;
  59. let mut cfg = cfg.replace("'", "\"");
  60. if json_params.is_some() {
  61. cfg = json_params.unwrap();
  62. }
  63. let seed_buf = (*seed).try_into().unwrap();
  64. let params = Box::leak(Box::new(params_from_json(&cfg)));
  65. let rng = Box::leak(Box::new(ChaCha20Rng::from_seed(seed_buf)));
  66. let client = Box::leak(Box::new(Client::init(params, rng)));
  67. WrappedClient { client }
  68. }
  69. #[wasm_bindgen]
  70. pub fn generate_public_parameters(c: &mut WrappedClient) -> Box<[u8]> {
  71. let res = c.client.generate_keys().serialize().into_boxed_slice();
  72. // important to re-seed here; only query and public key are deterministic
  73. let mut rng = thread_rng();
  74. let mut new_seed = [0u8; 32];
  75. rng.fill_bytes(&mut new_seed);
  76. *c.client.get_rng() = ChaCha20Rng::from_seed(new_seed);
  77. res
  78. }
  79. #[wasm_bindgen]
  80. pub fn generate_query(c: &mut WrappedClient, id: &str, idx_target: usize) -> Box<[u8]> {
  81. assert_eq!(id.len(), UUID_V4_LEN);
  82. let query = c.client.generate_query(idx_target);
  83. let mut query_buf = query.serialize();
  84. let mut full_query_buf = id.as_bytes().to_vec();
  85. full_query_buf.append(&mut query_buf);
  86. full_query_buf.into_boxed_slice()
  87. }
  88. #[wasm_bindgen]
  89. pub fn decode_response(c: &mut WrappedClient, data: Box<[u8]>) -> Box<[u8]> {
  90. c.client.decode_response(&*data).into_boxed_slice()
  91. }
  92. #[cfg(test)]
  93. mod test {
  94. use rand::{distributions::Standard, prelude::Distribution};
  95. use super::*;
  96. #[test]
  97. fn chacha_is_correct() {
  98. let mut rng1 = ChaCha20Rng::from_seed([1u8; 32]);
  99. let mut rng2 = ChaCha20Rng::from_seed([1u8; 32]);
  100. let val1: u64 = Standard.sample(&mut rng1);
  101. let val2: u64 = Standard.sample(&mut rng2);
  102. assert_eq!(val1, val2);
  103. }
  104. }