From aa75f85e17699cb84926fa33b1cd800d18abac6e Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Tue, 24 Jan 2023 15:11:22 +0100 Subject: [PATCH 01/36] add a benchmark sketch --- tpke/README.md | 11 ++- tpke/examples/bench_primitives_size.rs | 98 ++++++++++++++++++++++++++ tpke/src/lib.rs | 4 +- 3 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 tpke/examples/bench_primitives_size.rs diff --git a/tpke/README.md b/tpke/README.md index cf7ddad7..89a0d94b 100644 --- a/tpke/README.md +++ b/tpke/README.md @@ -1,9 +1,18 @@ # tpke -## Benchmarking WASM +## Benchmarks + +### Benchmarking WASM Based on `centurion.rs` (docs)[https://github.com/bheisler/criterion.rs/blob/version-0.4/book/src/user_guide/wasi.md#webasseblywasi-benchmarking] +### Benchmarking primitives size + +```sh +cargo run --example bench_primitives_size +``` + + ### Setup ```bash diff --git a/tpke/examples/bench_primitives_size.rs b/tpke/examples/bench_primitives_size.rs new file mode 100644 index 00000000..f7c691a1 --- /dev/null +++ b/tpke/examples/bench_primitives_size.rs @@ -0,0 +1,98 @@ +use ark_serialize::CanonicalSerialize; +use group_threshold_cryptography::{ + encrypt, prepare_combine_simple, setup_simple, share_combine_simple, +}; +use rand_core::RngCore; +use std::fs::{create_dir_all, OpenOptions}; +use std::io::prelude::*; +use std::path::Path; + +pub fn update_benchmark( + threshold: usize, + shares_num: usize, + pubkey_share_serialized_size: usize, + privkey_share_serialized_size: usize, +) { + let dir_path = Path::new("/tmp/benchmark_setup"); + create_dir_all(dir_path).unwrap(); + + let file_path = dir_path.join("results.md"); + eprintln!("Saving setup results to file: {}", file_path.display()); + + if !file_path.exists() { + let mut file = OpenOptions::new() + .create(true) + .write(true) + .open(&file_path) + .unwrap(); + + writeln!( + file, + "|threshold|shares_num|pubkey_share_serialized_size|privkey_share_serialized_size|", + ) + .unwrap(); + + writeln!(file, "|---|---|---|---|",).unwrap(); + } + + let mut file = OpenOptions::new().append(true).open(&file_path).unwrap(); + + writeln!( + file, + "|{}|{}|{}|{}|", + threshold, + shares_num, + pubkey_share_serialized_size, + privkey_share_serialized_size, + ) + .unwrap(); +} + +type E = ark_bls12_381::Bls12_381; + +fn main() { + for shares_num in [2, 4, 8, 16, 32, 64] { + let rng = &mut rand::thread_rng(); + + let msg_size = 256; + let threshold = shares_num * 2 / 3; + + let mut msg: Vec = vec![0u8; msg_size]; + rng.fill_bytes(&mut msg[..]); + let aad: &[u8] = "my-aad".as_bytes(); + + let (pubkey, _privkey, contexts) = + setup_simple::(threshold, shares_num, rng); + + // Ciphertext.commitment is already computed to match U + let ciphertext = encrypt::<_, E>(&msg, aad, &pubkey, rng); + + // Creating decryption shares + let decryption_shares: Vec<_> = contexts + .iter() + .map(|context| context.create_share(&ciphertext)) + .collect(); + + let pub_contexts = &contexts[0].public_decryption_contexts; + let domain: Vec<_> = pub_contexts.iter().map(|c| c.domain).collect(); + let lagrange = prepare_combine_simple::(&domain); + + let _shared_secret = + share_combine_simple::(&decryption_shares, &lagrange); + + let pub_context = &contexts[0].public_decryption_contexts[0]; + + update_benchmark( + threshold, + shares_num, + pub_context + .public_key_share + .public_key_share + .serialized_size(), + contexts[0] + .private_key_share + .private_key_share + .serialized_size(), + ); + } +} diff --git a/tpke/src/lib.rs b/tpke/src/lib.rs index b2be3ff6..e7e1c0ae 100644 --- a/tpke/src/lib.rs +++ b/tpke/src/lib.rs @@ -208,7 +208,7 @@ pub fn setup_simple( let pubkey_shares = subproductdomain::fast_multiexp(&evals.evals, g.into_projective()); let pubkey_share = g.mul(evals.evals[0]); - assert!(pubkey_shares[0] == E::G1Affine::from(pubkey_share)); + debug_assert!(pubkey_shares[0] == E::G1Affine::from(pubkey_share)); // Y, but only when b = 1 - private key shares of participants let privkey_shares = @@ -221,7 +221,7 @@ pub fn setup_simple( let privkey = h.mul(x); let secret = threshold_poly.evaluate(&E::Fr::zero()); - assert_eq!(secret, x); + debug_assert!(secret == x); let mut private_contexts = vec![]; let mut public_contexts = vec![]; From 6c28d48ddc8aa0805b0fdb634564a627baf1f52f Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Fri, 27 Jan 2023 13:31:48 +0100 Subject: [PATCH 02/36] benchmark size of pvss transcripts --- Cargo.lock | 15 ++-- ferveo/Cargo.toml | 3 +- ferveo/README.md | 9 ++ ferveo/examples/bench_primitives_size.rs | 107 +++++++++++++++++++++++ tpke/README.md | 7 -- tpke/examples/bench_primitives_size.rs | 98 --------------------- 6 files changed, 126 insertions(+), 113 deletions(-) create mode 100644 ferveo/README.md create mode 100644 ferveo/examples/bench_primitives_size.rs delete mode 100644 tpke/examples/bench_primitives_size.rs diff --git a/Cargo.lock b/Cargo.lock index 6e875f54..3384344a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -673,7 +673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", - "rand_core 0.6.3", + "rand_core 0.6.4", "typenum", ] @@ -902,6 +902,7 @@ dependencies = [ "pprof", "rand 0.7.3", "rand 0.8.5", + "rand_core 0.6.4", "serde", "serde_bytes", "serde_json", @@ -1002,7 +1003,7 @@ dependencies = [ "itertools", "miracl_core", "rand 0.8.5", - "rand_core 0.6.3", + "rand_core 0.6.4", "rayon", "serde", "serde_with", @@ -1647,7 +1648,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -1667,7 +1668,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -1681,9 +1682,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.7", ] @@ -2156,7 +2157,7 @@ dependencies = [ "group-threshold-cryptography", "js-sys", "rand 0.8.5", - "rand_core 0.6.3", + "rand_core 0.6.4", "serde", "serde_with", "wasm-bindgen", diff --git a/ferveo/Cargo.toml b/ferveo/Cargo.toml index 007ac763..37015d77 100644 --- a/ferveo/Cargo.toml +++ b/ferveo/Cargo.toml @@ -40,6 +40,7 @@ ark-ed-on-bls12-381 = "0.3.0" group-threshold-cryptography = { path = "../tpke" } ferveo-common = { path = "../ferveo-common" } subproductdomain = { path = "../subproductdomain" } +rand_core = "0.6.4" [dependencies.digest] version = "0.10.0" @@ -60,4 +61,4 @@ harness = false [profile.release] opt-level = 3 -lto = true \ No newline at end of file +lto = true diff --git a/ferveo/README.md b/ferveo/README.md new file mode 100644 index 00000000..6b63e57b --- /dev/null +++ b/ferveo/README.md @@ -0,0 +1,9 @@ +# ferveo + +## Benchmarks + +### Benchmarking primitives size + +```sh +cargo run --example bench_primitives_size +``` diff --git a/ferveo/examples/bench_primitives_size.rs b/ferveo/examples/bench_primitives_size.rs new file mode 100644 index 00000000..500993ae --- /dev/null +++ b/ferveo/examples/bench_primitives_size.rs @@ -0,0 +1,107 @@ +use ark_serialize::CanonicalSerialize; + +use ark_bls12_381::Bls12_381 as EllipticCurve; +use ferveo::*; +use ferveo_common::ExternalValidator; +use rand::prelude::StdRng; +use rand_core::SeedableRng; +use std::fs::{create_dir_all, OpenOptions}; +use std::io::prelude::*; +use std::path::Path; + +pub fn save_data(threshold: usize, shares_num: usize, transcript_size: usize) { + let dir_path = Path::new("/tmp/benchmark_setup"); + create_dir_all(dir_path).unwrap(); + let file_path = dir_path.join("results.md"); + + if !file_path.exists() { + eprintln!("Creating a new file: {}", file_path.display()); + let mut file = OpenOptions::new() + .create(true) + .write(true) + .open(&file_path) + .unwrap(); + writeln!(file, "|threshold|shares_num|pvss_transcript_size|",).unwrap(); + writeln!(file, "|---|---|---|",).unwrap(); + } + + eprintln!("Appending to file: {}", file_path.display()); + let mut file = OpenOptions::new().append(true).open(&file_path).unwrap(); + writeln!(file, "|{}|{}|{}|", threshold, shares_num, transcript_size,) + .unwrap(); +} + +// TODO: Find a way to deduplicate the following methods with benchmarks and test setup + +fn gen_keypairs(num: u32) -> Vec> { + let rng = &mut ark_std::test_rng(); + (0..num) + .map(|_| ferveo_common::Keypair::::new(rng)) + .collect() +} + +fn gen_validators( + keypairs: &[ferveo_common::Keypair], +) -> Vec> { + (0..keypairs.len()) + .map(|i| ExternalValidator { + address: format!("validator_{}", i), + public_key: keypairs[i].public(), + }) + .collect() +} + +fn setup_dkg( + validator: usize, + shares_num: u32, +) -> PubliclyVerifiableDkg { + let keypairs = gen_keypairs(shares_num); + let validators = gen_validators(&keypairs); + let me = validators[validator].clone(); + PubliclyVerifiableDkg::new( + validators, + Params { + tau: 0, + security_threshold: shares_num / 3, + shares_num, + retry_after: 1, + }, + &me, + keypairs[validator], + ) + .expect("Setup failed") +} + +fn setup( + shares_num: u32, + rng: &mut StdRng, +) -> PubliclyVerifiableDkg { + let mut transcripts = vec![]; + for i in 0..shares_num { + let mut dkg = setup_dkg(i as usize, shares_num); + transcripts.push(dkg.share(rng).expect("Test failed")); + } + + let mut dkg = setup_dkg(0, shares_num); + for (sender, pvss) in transcripts.into_iter().enumerate() { + dkg.apply_message(dkg.validators[sender].validator.clone(), pvss) + .expect("Setup failed"); + } + dkg +} + +fn main() { + let rng = &mut StdRng::seed_from_u64(0); + + for shares_num in [2, 4, 8, 16, 32, 64] { + let dkg = setup(shares_num as u32, rng); + let mut transcript_bytes = vec![]; + dkg.vss[&0].serialize(&mut transcript_bytes).unwrap(); + + save_data( + dkg.params.security_threshold as usize, + shares_num, + transcript_bytes.len(), + ); + } +} diff --git a/tpke/README.md b/tpke/README.md index 89a0d94b..e48dc7ea 100644 --- a/tpke/README.md +++ b/tpke/README.md @@ -6,13 +6,6 @@ Based on `centurion.rs` (docs)[https://github.com/bheisler/criterion.rs/blob/version-0.4/book/src/user_guide/wasi.md#webasseblywasi-benchmarking] -### Benchmarking primitives size - -```sh -cargo run --example bench_primitives_size -``` - - ### Setup ```bash diff --git a/tpke/examples/bench_primitives_size.rs b/tpke/examples/bench_primitives_size.rs deleted file mode 100644 index f7c691a1..00000000 --- a/tpke/examples/bench_primitives_size.rs +++ /dev/null @@ -1,98 +0,0 @@ -use ark_serialize::CanonicalSerialize; -use group_threshold_cryptography::{ - encrypt, prepare_combine_simple, setup_simple, share_combine_simple, -}; -use rand_core::RngCore; -use std::fs::{create_dir_all, OpenOptions}; -use std::io::prelude::*; -use std::path::Path; - -pub fn update_benchmark( - threshold: usize, - shares_num: usize, - pubkey_share_serialized_size: usize, - privkey_share_serialized_size: usize, -) { - let dir_path = Path::new("/tmp/benchmark_setup"); - create_dir_all(dir_path).unwrap(); - - let file_path = dir_path.join("results.md"); - eprintln!("Saving setup results to file: {}", file_path.display()); - - if !file_path.exists() { - let mut file = OpenOptions::new() - .create(true) - .write(true) - .open(&file_path) - .unwrap(); - - writeln!( - file, - "|threshold|shares_num|pubkey_share_serialized_size|privkey_share_serialized_size|", - ) - .unwrap(); - - writeln!(file, "|---|---|---|---|",).unwrap(); - } - - let mut file = OpenOptions::new().append(true).open(&file_path).unwrap(); - - writeln!( - file, - "|{}|{}|{}|{}|", - threshold, - shares_num, - pubkey_share_serialized_size, - privkey_share_serialized_size, - ) - .unwrap(); -} - -type E = ark_bls12_381::Bls12_381; - -fn main() { - for shares_num in [2, 4, 8, 16, 32, 64] { - let rng = &mut rand::thread_rng(); - - let msg_size = 256; - let threshold = shares_num * 2 / 3; - - let mut msg: Vec = vec![0u8; msg_size]; - rng.fill_bytes(&mut msg[..]); - let aad: &[u8] = "my-aad".as_bytes(); - - let (pubkey, _privkey, contexts) = - setup_simple::(threshold, shares_num, rng); - - // Ciphertext.commitment is already computed to match U - let ciphertext = encrypt::<_, E>(&msg, aad, &pubkey, rng); - - // Creating decryption shares - let decryption_shares: Vec<_> = contexts - .iter() - .map(|context| context.create_share(&ciphertext)) - .collect(); - - let pub_contexts = &contexts[0].public_decryption_contexts; - let domain: Vec<_> = pub_contexts.iter().map(|c| c.domain).collect(); - let lagrange = prepare_combine_simple::(&domain); - - let _shared_secret = - share_combine_simple::(&decryption_shares, &lagrange); - - let pub_context = &contexts[0].public_decryption_contexts[0]; - - update_benchmark( - threshold, - shares_num, - pub_context - .public_key_share - .public_key_share - .serialized_size(), - contexts[0] - .private_key_share - .private_key_share - .serialized_size(), - ); - } -} From feb8d8077564b43a5dae255b30e842ae75e2e85b Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Fri, 27 Jan 2023 16:32:55 +0100 Subject: [PATCH 03/36] benchmark per ratio with no duplicates --- ferveo/examples/bench_primitives_size.rs | 75 ++++++++++++++++-------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/ferveo/examples/bench_primitives_size.rs b/ferveo/examples/bench_primitives_size.rs index 500993ae..56655aa3 100644 --- a/ferveo/examples/bench_primitives_size.rs +++ b/ferveo/examples/bench_primitives_size.rs @@ -1,33 +1,43 @@ use ark_serialize::CanonicalSerialize; +use std::collections::BTreeSet; use ark_bls12_381::Bls12_381 as EllipticCurve; use ferveo::*; use ferveo_common::ExternalValidator; +use itertools::iproduct; use rand::prelude::StdRng; use rand_core::SeedableRng; use std::fs::{create_dir_all, OpenOptions}; use std::io::prelude::*; -use std::path::Path; +use std::path::PathBuf; -pub fn save_data(threshold: usize, shares_num: usize, transcript_size: usize) { - let dir_path = Path::new("/tmp/benchmark_setup"); +const OUTPUT_DIR_PATH: &str = "/tmp/benchmark_setup"; +const OUTPUT_FILE_NAME: &str = "results.md"; + +pub fn create_or_truncate_output_file() -> std::io::Result<()> { + let file_path = PathBuf::from(OUTPUT_DIR_PATH).join(OUTPUT_FILE_NAME); + eprintln!("Creating output file at {}", file_path.display()); + + let dir_path = PathBuf::from(OUTPUT_DIR_PATH); create_dir_all(dir_path).unwrap(); - let file_path = dir_path.join("results.md"); - - if !file_path.exists() { - eprintln!("Creating a new file: {}", file_path.display()); - let mut file = OpenOptions::new() - .create(true) - .write(true) - .open(&file_path) - .unwrap(); - writeln!(file, "|threshold|shares_num|pvss_transcript_size|",).unwrap(); - writeln!(file, "|---|---|---|",).unwrap(); - } + + let mut file = OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(file_path)?; + file.sync_all()?; + + writeln!(file, "|shares_num|threshold|pvss_transcript_size|",)?; + writeln!(file, "|---|---|---|---|") +} + +pub fn save_data(shares_num: usize, threshold: usize, transcript_size: usize) { + let file_path = PathBuf::from(OUTPUT_DIR_PATH).join(OUTPUT_FILE_NAME); eprintln!("Appending to file: {}", file_path.display()); let mut file = OpenOptions::new().append(true).open(&file_path).unwrap(); - writeln!(file, "|{}|{}|{}|", threshold, shares_num, transcript_size,) + writeln!(file, "{}|{}|{}|", shares_num, threshold, transcript_size) .unwrap(); } @@ -54,6 +64,7 @@ fn gen_validators( fn setup_dkg( validator: usize, shares_num: u32, + security_threshold: u32, ) -> PubliclyVerifiableDkg { let keypairs = gen_keypairs(shares_num); let validators = gen_validators(&keypairs); @@ -62,7 +73,7 @@ fn setup_dkg( validators, Params { tau: 0, - security_threshold: shares_num / 3, + security_threshold, shares_num, retry_after: 1, }, @@ -74,15 +85,16 @@ fn setup_dkg( fn setup( shares_num: u32, + security_threshold: u32, rng: &mut StdRng, ) -> PubliclyVerifiableDkg { let mut transcripts = vec![]; for i in 0..shares_num { - let mut dkg = setup_dkg(i as usize, shares_num); + let mut dkg = setup_dkg(i as usize, shares_num, security_threshold); transcripts.push(dkg.share(rng).expect("Test failed")); } - let mut dkg = setup_dkg(0, shares_num); + let mut dkg = setup_dkg(0, shares_num, security_threshold); for (sender, pvss) in transcripts.into_iter().enumerate() { dkg.apply_message(dkg.validators[sender].validator.clone(), pvss) .expect("Setup failed"); @@ -93,14 +105,31 @@ fn setup( fn main() { let rng = &mut StdRng::seed_from_u64(0); - for shares_num in [2, 4, 8, 16, 32, 64] { - let dkg = setup(shares_num as u32, rng); + create_or_truncate_output_file().unwrap(); + + let share_num_vec = [2, 4, 8, 16, 32, 64]; + let threshold_ratio_vec = [0.51, 0.66, 0.8, 1.0]; + + // Create benchmark parameters without duplicates + let configs = iproduct!(&share_num_vec, &threshold_ratio_vec) + .map(|(shares_num, threshold_ratio)| { + let threshold = + (*shares_num as f64 * threshold_ratio).ceil() as u32; + (shares_num, threshold) + }) + .collect::>(); + + println!("Running benchmarks for {:?}", configs); + + for (shares_num, threshold) in configs { + println!("shares_num: {}, threshold: {}", shares_num, threshold); + let dkg = setup(*shares_num as u32, threshold, rng); let mut transcript_bytes = vec![]; dkg.vss[&0].serialize(&mut transcript_bytes).unwrap(); save_data( - dkg.params.security_threshold as usize, - shares_num, + threshold as usize, + *shares_num as usize, transcript_bytes.len(), ); } From 076f2610c753bb02cd5fe5a2219679f63cdffdea Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Fri, 27 Jan 2023 18:04:18 +0100 Subject: [PATCH 04/36] fix switched columns --- ferveo/examples/bench_primitives_size.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ferveo/examples/bench_primitives_size.rs b/ferveo/examples/bench_primitives_size.rs index 56655aa3..c03a6a94 100644 --- a/ferveo/examples/bench_primitives_size.rs +++ b/ferveo/examples/bench_primitives_size.rs @@ -128,8 +128,8 @@ fn main() { dkg.vss[&0].serialize(&mut transcript_bytes).unwrap(); save_data( - threshold as usize, *shares_num as usize, + threshold as usize, transcript_bytes.len(), ); } From 6966b28e3ee273f51c73402ac986a03e10743139 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Fri, 27 Jan 2023 22:50:21 +0100 Subject: [PATCH 05/36] set polynomial degree to t-1 in pvss --- ferveo/src/vss/pvss.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ferveo/src/vss/pvss.rs b/ferveo/src/vss/pvss.rs index 719a0ab0..d622e009 100644 --- a/ferveo/src/vss/pvss.rs +++ b/ferveo/src/vss/pvss.rs @@ -72,7 +72,7 @@ impl PubliclyVerifiableSS { ) -> Result { // Our random polynomial, \phi(x) = s + \sum_{i=1}^{t-1} a_i x^i let mut phi = DensePolynomial::::rand( - (dkg.params.shares_num - dkg.params.security_threshold) as usize, + (dkg.params.security_threshold - 1) as usize, rng, ); phi.coeffs[0] = *s; // setting the first coefficient to secret value @@ -302,10 +302,7 @@ mod test_pvss { // check that the chosen secret coefficient is correct assert_eq!(pvss.coeffs[0], G1::prime_subgroup_generator().mul(s)); //check that a polynomial of the correct degree was created - assert_eq!( - pvss.coeffs.len(), - dkg.params.security_threshold as usize + 1 - ); + assert_eq!(pvss.coeffs.len(), dkg.params.security_threshold as usize); // check that the correct number of shares were created assert_eq!(pvss.shares.len(), dkg.validators.len()); // check that the prove of knowledge is correct @@ -344,7 +341,7 @@ mod test_pvss { //check that a polynomial of the correct degree was created assert_eq!( aggregate.coeffs.len(), - dkg.params.security_threshold as usize + 1 + dkg.params.security_threshold as usize ); // check that the correct number of shares were created assert_eq!(aggregate.shares.len(), dkg.validators.len()); From 6f1b7d4c7086517f7960a0388acd17baf78504b1 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Mon, 30 Jan 2023 10:53:55 +0100 Subject: [PATCH 06/36] size is expressed in bytes --- ferveo/examples/bench_primitives_size.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ferveo/examples/bench_primitives_size.rs b/ferveo/examples/bench_primitives_size.rs index c03a6a94..e7a0857b 100644 --- a/ferveo/examples/bench_primitives_size.rs +++ b/ferveo/examples/bench_primitives_size.rs @@ -28,17 +28,25 @@ pub fn create_or_truncate_output_file() -> std::io::Result<()> { .open(file_path)?; file.sync_all()?; - writeln!(file, "|shares_num|threshold|pvss_transcript_size|",)?; + writeln!(file, "|shares_num|threshold|pvss_transcript_size_bytes|",)?; writeln!(file, "|---|---|---|---|") } -pub fn save_data(shares_num: usize, threshold: usize, transcript_size: usize) { +pub fn save_data( + shares_num: usize, + threshold: usize, + transcript_size_bytes: usize, +) { let file_path = PathBuf::from(OUTPUT_DIR_PATH).join(OUTPUT_FILE_NAME); eprintln!("Appending to file: {}", file_path.display()); let mut file = OpenOptions::new().append(true).open(&file_path).unwrap(); - writeln!(file, "{}|{}|{}|", shares_num, threshold, transcript_size) - .unwrap(); + writeln!( + file, + "{}|{}|{}|", + shares_num, threshold, transcript_size_bytes + ) + .unwrap(); } // TODO: Find a way to deduplicate the following methods with benchmarks and test setup From 33b2b0954d08261e72a7d206446a689fc6b251ac Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Mon, 30 Jan 2023 22:02:48 +0100 Subject: [PATCH 07/36] update tpke client api --- .github/workflows/workspace.yml | 21 ++++++++ tpke-wasm/src/lib.rs | 24 +++------ tpke-wasm/tests/node.rs | 4 +- tpke/src/api.rs | 41 +++++++++++---- tpke/src/ciphertext.rs | 93 ++++++++++++++++++++++++++++++++- tpke/src/lib.rs | 85 +----------------------------- 6 files changed, 155 insertions(+), 113 deletions(-) diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index 570698ab..db9463b8 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -77,6 +77,27 @@ jobs: - run: cargo check --all-features - run: cargo test --release --all-features + wasm-test: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - 1.63 # MSRV + - stable + target: + - wasm32-unknown-unknown + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + target: ${{ matrix.target }} + override: true + - run: cargo install wasm-pack + - run: wasm-pack test --node + working-directory: tpke-wasm + benchmark: runs-on: ubuntu-latest needs: [ test ] diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index d59e0d8c..647cb884 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -5,20 +5,12 @@ extern crate group_threshold_cryptography as tpke; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use serde::{Deserialize, Serialize}; use serde_with::serde_as; +use tpke::api::*; use utils::set_panic_hook; use wasm_bindgen::prelude::*; extern crate wee_alloc; -pub type E = ark_bls12_381::Bls12_381; -pub type TpkePublicKey = ark_bls12_381::G1Affine; -pub type TpkePrivateKey = ark_bls12_381::G2Affine; -pub type TpkeCiphertext = tpke::Ciphertext; -pub type TpkeDecryptionShare = tpke::DecryptionShareFast; -pub type TpkePublicDecryptionContext = tpke::PublicDecryptionContextFast; -pub type TpkeSharedSecret = - ::Fqk; - #[wasm_bindgen] #[derive(Clone, Debug)] pub struct PrivateDecryptionContext(tpke::api::PrivateDecryptionContext); @@ -214,7 +206,7 @@ impl Setup { .collect() } - // TODO: Add `decryptorShares` helper method + // TODO: Add `decryptorShares` helper method? } #[wasm_bindgen] @@ -231,10 +223,7 @@ pub fn encrypt( public_key: &PublicKey, ) -> Ciphertext { set_panic_hook(); - - let mut rng = rand::thread_rng(); - let ciphertext = - tpke::encrypt::<_, E>(message, aad, &public_key.0, &mut rng); + let ciphertext = tpke::api::encrypt(message, aad, &public_key.0); Ciphertext { ciphertext, aad: aad.to_vec(), @@ -242,7 +231,10 @@ pub fn encrypt( } #[wasm_bindgen] -pub fn decrypt(ciphertext: &Ciphertext, private_key: &PrivateKey) -> Vec { +pub fn decrypt_with_private_key( + ciphertext: &Ciphertext, + private_key: &PrivateKey, +) -> Vec { set_panic_hook(); tpke::decrypt_symmetric( @@ -308,7 +300,7 @@ pub fn decrypt_with_shared_secret( ) -> Vec { set_panic_hook(); - tpke::decrypt_with_shared_secret( + tpke::api::decrypt_with_shared_secret( &ciphertext.ciphertext, &ciphertext.aad, &shared_secret.0, diff --git a/tpke-wasm/tests/node.rs b/tpke-wasm/tests/node.rs index ec935180..d9e14972 100644 --- a/tpke-wasm/tests/node.rs +++ b/tpke-wasm/tests/node.rs @@ -5,8 +5,6 @@ extern crate wasm_bindgen_test; use tpke_wasm::*; use wasm_bindgen_test::*; -extern crate group_threshold_cryptography as tpke; - #[test] #[wasm_bindgen_test] pub fn participant_payload_serialization() { @@ -39,7 +37,7 @@ fn encrypts_and_decrypts() { let setup = Setup::new(threshold, shares_num); let ciphertext = encrypt(&message, &aad, &setup.public_key); - let plaintext = decrypt(&ciphertext, &setup.private_key); + let plaintext = decrypt_with_private_key(&ciphertext, &setup.private_key); // TODO: Plaintext is padded to 32 bytes. Fix this. assert_eq!(message, plaintext[..message.len()]) diff --git a/tpke/src/api.rs b/tpke/src/api.rs index 772f63f5..33fa3597 100644 --- a/tpke/src/api.rs +++ b/tpke/src/api.rs @@ -4,21 +4,41 @@ // TODO: Refactor this module to deduplicate shared code from tpke-wasm and tpke-wasm. -use std::convert::TryInto; - use ark_ec::{AffineCurve, ProjectiveCurve}; use ark_ff::{BigInteger256, ToBytes}; +use std::convert::TryInto; // Fixing some of the types here on our target engine // TODO: Consider fixing on crate::api level instead of bindings level -type E = ark_bls12_381::Bls12_381; -type TpkePublicKey = ark_bls12_381::G1Affine; -type TpkePrivateKey = ark_bls12_381::G2Affine; -type TpkeCiphertext = crate::Ciphertext; -type TpkeDecryptionShare = crate::DecryptionShareFast; -type TpkePublicDecryptionContext = crate::PublicDecryptionContextFast; -type TpkeSharedSecret = +pub type E = ark_bls12_381::Bls12_381; +pub type TpkePublicKey = ark_bls12_381::G1Affine; +pub type TpkePrivateKey = ark_bls12_381::G2Affine; +pub type TpkeCiphertext = crate::Ciphertext; +pub type TpkeDecryptionShare = crate::DecryptionShareFast; +pub type TpkePublicDecryptionContext = crate::PublicDecryptionContextFast; +pub type TpkeSharedSecret = ::Fqk; +pub type TpkeResult = crate::Result; + +pub fn encrypt( + message: &[u8], + aad: &[u8], + pubkey: &TpkePublicKey, +) -> TpkeCiphertext { + let rng = &mut rand::thread_rng(); + crate::encrypt(message, aad, pubkey, rng) +} + +pub fn decrypt_with_shared_secret( + ciphertext: &TpkeCiphertext, + aad: &[u8], + shared_secret: &TpkeSharedSecret, +) -> TpkeResult> { + crate::decrypt_with_shared_secret(ciphertext, aad, shared_secret) +} + +// TODO: There is previous API implementation below. I'm not removing it to avoid breaking bindings. +// Review it and decide if we need it. #[derive(Clone, Debug)] pub struct PrivateDecryptionContext { @@ -92,11 +112,14 @@ impl DecryptionShare { } } +// TODO: Reconsider contents of ParticipantPayload payload after updating server API. + #[derive(Clone, Debug)] pub struct ParticipantPayload { pub decryption_context: PrivateDecryptionContext, pub ciphertext: TpkeCiphertext, } + impl ParticipantPayload { pub fn new( decryption_context: &PrivateDecryptionContext, diff --git a/tpke/src/ciphertext.rs b/tpke/src/ciphertext.rs index c9d13b9f..ebe75cd1 100644 --- a/tpke/src/ciphertext.rs +++ b/tpke/src/ciphertext.rs @@ -9,8 +9,6 @@ use chacha20poly1305::{ }; use rand_core::RngCore; -use crate::{construct_tag_hash, hash_to_g2}; - #[derive(Clone, Debug)] pub struct Ciphertext { pub commitment: E::G1Affine, // U @@ -191,3 +189,94 @@ fn nonce_from_commitment(commitment: E::G1Affine) -> Nonce { let commitment_hash = blake2s_hash(&commitment_bytes); *Nonce::from_slice(&commitment_hash[..12]) } + +fn hash_to_g2(message: &[u8]) -> T { + let mut point_ser: Vec = Vec::new(); + let point = htp_bls12381_g2(message); + point.serialize(&mut point_ser).unwrap(); + T::deserialize(&point_ser[..]).unwrap() +} + +fn construct_tag_hash( + u: E::G1Affine, + stream_ciphertext: &[u8], + aad: &[u8], +) -> E::G2Affine { + let mut hash_input = Vec::::new(); + u.write(&mut hash_input).unwrap(); + hash_input.extend_from_slice(stream_ciphertext); + hash_input.extend_from_slice(aad); + + hash_to_g2(&hash_input) +} + +#[cfg(test)] +mod tests { + use crate::{ + check_ciphertext_validity, decrypt_symmetric, encrypt, setup_fast, + Ciphertext, + }; + use ark_bls12_381::{Fr, G1Projective, G2Projective}; + use ark_ec::ProjectiveCurve; + use ark_ff::PrimeField; + use ark_std::{test_rng, UniformRand}; + use rand::prelude::StdRng; + + type E = ark_bls12_381::Bls12_381; + + #[test] + fn ciphertext_serialization() { + let rng = &mut test_rng(); + let msg: &[u8] = "abc".as_bytes(); + let aad: &[u8] = "my-aad".as_bytes(); + let pubkey = G1Projective::rand(rng).into_affine(); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); + + let serialized = ciphertext.to_bytes(); + let deserialized: Ciphertext = Ciphertext::from_bytes(&serialized); + + assert_eq!(serialized, deserialized.to_bytes()) + } + + #[test] + fn symmetric_encryption() { + let rng = &mut test_rng(); + let msg: &[u8] = "abc".as_bytes(); + let aad: &[u8] = "my-aad".as_bytes(); + + let x = Fr::rand(rng).into_repr(); + let pubkey = G1Projective::prime_subgroup_generator() + .mul(x) + .into_affine(); + let privkey = G2Projective::prime_subgroup_generator() + .mul(x) + .into_affine(); + + let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let plaintext = decrypt_symmetric(&ciphertext, aad, privkey).unwrap(); + + assert_eq!(msg, plaintext) + } + + #[test] + fn ciphertext_validity_check() { + let rng = &mut test_rng(); + let shares_num = 16; + let threshold = shares_num * 2 / 3; + let msg: &[u8] = "abc".as_bytes(); + let aad: &[u8] = "my-aad".as_bytes(); + let (pubkey, _, _) = setup_fast::(threshold, shares_num, rng); + let mut ciphertext = encrypt::(msg, aad, &pubkey, rng); + + // So far, the ciphertext is valid + assert!(check_ciphertext_validity(&ciphertext, aad).is_ok()); + + // Malformed the ciphertext + ciphertext.ciphertext[0] += 1; + assert!(check_ciphertext_validity(&ciphertext, aad).is_err()); + + // Malformed the AAD + let aad = "bad aad".as_bytes(); + assert!(check_ciphertext_validity(&ciphertext, aad).is_err()); + } +} diff --git a/tpke/src/lib.rs b/tpke/src/lib.rs index c961d8df..35d69f67 100644 --- a/tpke/src/lib.rs +++ b/tpke/src/lib.rs @@ -2,18 +2,15 @@ use crate::hash_to_curve::htp_bls12381_g2; use crate::SetupParams; use ark_ec::{AffineCurve, PairingEngine}; -use ark_ff::{Field, One, PrimeField, ToBytes, UniformRand, Zero}; +use ark_ff::{Field, One, PrimeField, UniformRand, Zero}; use ark_poly::{ univariate::DensePolynomial, EvaluationDomain, Polynomial, UVPolynomial, }; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use itertools::izip; - -use subproductdomain::{fast_multiexp, SubproductDomain}; - use rand_core::RngCore; use std::usize; - +use subproductdomain::{fast_multiexp, SubproductDomain}; use thiserror::Error; mod ciphertext; @@ -61,26 +58,6 @@ pub enum ThresholdEncryptionError { pub type Result = std::result::Result; -fn hash_to_g2(message: &[u8]) -> T { - let mut point_ser: Vec = Vec::new(); - let point = htp_bls12381_g2(message); - point.serialize(&mut point_ser).unwrap(); - T::deserialize(&point_ser[..]).unwrap() -} - -fn construct_tag_hash( - u: E::G1Affine, - stream_ciphertext: &[u8], - aad: &[u8], -) -> E::G2Affine { - let mut hash_input = Vec::::new(); - u.write(&mut hash_input).unwrap(); - hash_input.extend_from_slice(stream_ciphertext); - hash_input.extend_from_slice(aad); - - hash_to_g2(&hash_input) -} - pub fn setup_fast( threshold: usize, shares_num: usize, @@ -374,64 +351,6 @@ mod tests { share_combine_simple::(decryption_shares, &lagrange) } - #[test] - fn ciphertext_serialization() { - let rng = &mut test_rng(); - let shares_num = 16; - let threshold = shares_num * 2 / 3; - let msg: &[u8] = "abc".as_bytes(); - let aad: &[u8] = "my-aad".as_bytes(); - - let (pubkey, _, _) = setup_fast::(threshold, shares_num, rng); - - let ciphertext = encrypt::(msg, aad, &pubkey, rng); - - let serialized = ciphertext.to_bytes(); - let deserialized: Ciphertext = Ciphertext::from_bytes(&serialized); - - assert_eq!(serialized, deserialized.to_bytes()) - } - - #[test] - fn symmetric_encryption() { - let rng = &mut test_rng(); - let shares_num = 16; - let threshold = shares_num * 2 / 3; - let msg: &[u8] = "abc".as_bytes(); - let aad: &[u8] = "my-aad".as_bytes(); - - let (pubkey, privkey, _) = setup_fast::(threshold, shares_num, rng); - - let ciphertext = encrypt::(msg, aad, &pubkey, rng); - - let plaintext = decrypt_symmetric(&ciphertext, aad, privkey).unwrap(); - - assert_eq!(msg, plaintext) - } - - #[test] - fn ciphertext_validity_check() { - let rng = &mut test_rng(); - let shares_num = 16; - let threshold = shares_num * 2 / 3; - let msg: &[u8] = "abc".as_bytes(); - let aad: &[u8] = "my-aad".as_bytes(); - - let (pubkey, _, _) = setup_fast::(threshold, shares_num, rng); - let mut ciphertext = encrypt::(msg, aad, &pubkey, rng); - - // So far, the ciphertext is valid - assert!(check_ciphertext_validity(&ciphertext, aad).is_ok()); - - // Malformed the ciphertext - ciphertext.ciphertext[0] += 1; - assert!(check_ciphertext_validity(&ciphertext, aad).is_err()); - - // Malformed the AAD - let aad = "bad aad".as_bytes(); - assert!(check_ciphertext_validity(&ciphertext, aad).is_err()); - } - #[test] fn fast_decryption_share_validation() { let rng = &mut test_rng(); From 9b0a4c6a532f477c5e581ad65d9ebc747824fce3 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Tue, 31 Jan 2023 12:57:22 +0100 Subject: [PATCH 08/36] setup ferveo-python for server api --- Cargo.lock | 21 + Cargo.toml | 1 + ferveo-python/.gitignore | 7 + ferveo-python/Cargo.toml | 16 + ferveo-python/LICENSE | 675 ++++++++++++++++++++++++++++++ ferveo-python/MANIFEST.in | 4 + ferveo-python/README.md | 5 + ferveo-python/build.rs | 3 + ferveo-python/ferveo/__init__.py | 4 + ferveo-python/ferveo/__init__.pyi | 22 + ferveo-python/ferveo/py.typed | 0 ferveo-python/pyproject.toml | 2 + ferveo-python/setup.py | 39 ++ ferveo-python/src/lib.rs | 37 ++ ferveo/src/api.rs | 41 ++ ferveo/src/dkg.rs | 1 + ferveo/src/dkg/pv.rs | 1 + ferveo/src/lib.rs | 37 +- tpke-python/src/lib.rs | 5 - 19 files changed, 894 insertions(+), 27 deletions(-) create mode 100644 ferveo-python/.gitignore create mode 100644 ferveo-python/Cargo.toml create mode 100755 ferveo-python/LICENSE create mode 100644 ferveo-python/MANIFEST.in create mode 100644 ferveo-python/README.md create mode 100644 ferveo-python/build.rs create mode 100644 ferveo-python/ferveo/__init__.py create mode 100644 ferveo-python/ferveo/__init__.pyi create mode 100644 ferveo-python/ferveo/py.typed create mode 100644 ferveo-python/pyproject.toml create mode 100644 ferveo-python/setup.py create mode 100644 ferveo-python/src/lib.rs create mode 100644 ferveo/src/api.rs diff --git a/Cargo.lock b/Cargo.lock index 6e875f54..c19b5168 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -811,6 +811,17 @@ dependencies = [ "syn", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "digest" version = "0.9.0" @@ -925,6 +936,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "ferveo-python" +version = "0.1.0" +dependencies = [ + "derive_more", + "ferveo", + "pyo3", + "pyo3-build-config", +] + [[package]] name = "findshlibs" version = "0.10.2" diff --git a/Cargo.toml b/Cargo.toml index 72edf305..94d18e5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "ferveo", "ferveo-common", + "ferveo-python", "subproductdomain", "tpke", "tpke-wasm", diff --git a/ferveo-python/.gitignore b/ferveo-python/.gitignore new file mode 100644 index 00000000..b2417b63 --- /dev/null +++ b/ferveo-python/.gitignore @@ -0,0 +1,7 @@ +__pycache__ +*.egg-info +*.so +build/ +dist/ +docs/_build + diff --git a/ferveo-python/Cargo.toml b/ferveo-python/Cargo.toml new file mode 100644 index 00000000..d8f14035 --- /dev/null +++ b/ferveo-python/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "ferveo-python" +authors = ["Piotr Roslaniec "] +version = "0.1.0" +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +pyo3 = "0.17.3" +ferveo = { path = "../ferveo" } +derive_more = { version = "0.99", default-features = false, features = ["from", "as_ref"] } + +[build-dependencies] +pyo3-build-config = "*" diff --git a/ferveo-python/LICENSE b/ferveo-python/LICENSE new file mode 100755 index 00000000..2fb2e74d --- /dev/null +++ b/ferveo-python/LICENSE @@ -0,0 +1,675 @@ +### GNU GENERAL PUBLIC LICENSE + +Version 3, 29 June 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. + + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +### Preamble + +The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom +to share and change all versions of a program--to make sure it remains +free software for all its users. We, the Free Software Foundation, use +the GNU General Public License for most of our software; it applies +also to any other work released this way by its authors. You can apply +it to your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you +have certain responsibilities if you distribute copies of the +software, or if you modify it: responsibilities to respect the freedom +of others. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + +Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the +manufacturer can do so. This is fundamentally incompatible with the +aim of protecting users' freedom to change the software. The +systematic pattern of such abuse occurs in the area of products for +individuals to use, which is precisely where it is most unacceptable. +Therefore, we have designed this version of the GPL to prohibit the +practice for those products. If such problems arise substantially in +other domains, we stand ready to extend this provision to those +domains in future versions of the GPL, as needed to protect the +freedom of users. + +Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish +to avoid the special danger that patents applied to a free program +could make it effectively proprietary. To prevent this, the GPL +assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and +modification follow. + +### TERMS AND CONDITIONS + +#### 0. Definitions. + +"This License" refers to version 3 of the GNU General Public License. + +"Copyright" also means copyright-like laws that apply to other kinds +of works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of +an exact copy. The resulting work is called a "modified version" of +the earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based +on the Program. + +To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user +through a computer network, with no transfer of a copy, is not +conveying. + +An interactive user interface displays "Appropriate Legal Notices" to +the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +#### 1. Source Code. + +The "source code" for a work means the preferred form of the work for +making modifications to it. "Object code" means any non-source form of +a work. + +A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can +regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same +work. + +#### 2. Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, +without conditions so long as your license otherwise remains in force. +You may convey covered works to others for the sole purpose of having +them make modifications exclusively for you, or provide you with +facilities for running those works, provided that you comply with the +terms of this License in conveying all material for which you do not +control copyright. Those thus making or running the covered works for +you must do so exclusively on your behalf, under your direction and +control, on terms that prohibit them from making any copies of your +copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the +conditions stated below. Sublicensing is not allowed; section 10 makes +it unnecessary. + +#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such +circumvention is effected by exercising rights under this License with +respect to the covered work, and you disclaim any intention to limit +operation or modification of the work as a means of enforcing, against +the work's users, your or third parties' legal rights to forbid +circumvention of technological measures. + +#### 4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +#### 5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these +conditions: + +- a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. +- b) The work must carry prominent notices stating that it is + released under this License and any conditions added under + section 7. This requirement modifies the requirement in section 4 + to "keep intact all notices". +- c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. +- d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +#### 6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of +sections 4 and 5, provided that you also convey the machine-readable +Corresponding Source under the terms of this License, in one of these +ways: + +- a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. +- b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the Corresponding + Source from a network server at no charge. +- c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. +- d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. +- e) Convey the object code using peer-to-peer transmission, + provided you inform other peers where the object code and + Corresponding Source of the work are being offered to the general + public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, +family, or household purposes, or (2) anything designed or sold for +incorporation into a dwelling. In determining whether a product is a +consumer product, doubtful cases shall be resolved in favor of +coverage. For a particular product received by a particular user, +"normally used" refers to a typical or common use of that class of +product, regardless of the status of the particular user or of the way +in which the particular user actually uses, or expects or is expected +to use, the product. A product is a consumer product regardless of +whether the product has substantial commercial, industrial or +non-consumer uses, unless such uses represent the only significant +mode of use of the product. + +"Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to +install and execute modified versions of a covered work in that User +Product from a modified version of its Corresponding Source. The +information must suffice to ensure that the continued functioning of +the modified object code is in no case prevented or interfered with +solely because modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or +updates for a work that has been modified or installed by the +recipient, or for the User Product in which it has been modified or +installed. Access to a network may be denied when the modification +itself materially and adversely affects the operation of the network +or violates the rules and protocols for communication across the +network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +#### 7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders +of that material) supplement the terms of this License with terms: + +- a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or +- b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or +- c) Prohibiting misrepresentation of the origin of that material, + or requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or +- d) Limiting the use for publicity purposes of names of licensors + or authors of the material; or +- e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or +- f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions + of it) with contractual assumptions of liability to the recipient, + for any liability that these contractual assumptions directly + impose on those licensors and authors. + +All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; the +above requirements apply either way. + +#### 8. Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +#### 9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run +a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +#### 10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +#### 11. Patents. + +A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims owned +or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is "discriminatory" if it does not include within the +scope of its coverage, prohibits the exercise of, or is conditioned on +the non-exercise of one or more of the rights that are specifically +granted under this License. You may not convey a covered work if you +are a party to an arrangement with a third party that is in the +business of distributing software, under which you make payment to the +third party based on the extent of your activity of conveying the +work, and under which the third party grants, to any of the parties +who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by +you (or copies made from those copies), or (b) primarily for and in +connection with specific products or compilations that contain the +covered work, unless you entered into that arrangement, or that patent +license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +#### 12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under +this License and any other pertinent obligations, then as a +consequence you may not convey it at all. For example, if you agree to +terms that obligate you to collect a royalty for further conveying +from those to whom you convey the Program, the only way you could +satisfy both those terms and this License would be to refrain entirely +from conveying the Program. + +#### 13. Use with the GNU Affero General Public License. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +#### 14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions +of the GNU General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in +detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies that a certain numbered version of the GNU General Public +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that numbered version or +of any later version published by the Free Software Foundation. If the +Program does not specify a version number of the GNU General Public +License, you may choose any version ever published by the Free +Software Foundation. + +If the Program specifies that a proxy can decide which future versions +of the GNU General Public License can be used, that proxy's public +statement of acceptance of a version permanently authorizes you to +choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +#### 15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + +#### 16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR +CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT +NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR +LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM +TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +#### 17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +### How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively state +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper +mail. + +If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands \`show w' and \`show c' should show the +appropriate parts of the General Public License. Of course, your +program's commands might be different; for a GUI interface, you would +use an "about box". + +You should also get your employer (if you work as a programmer) or +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. For more information on this, and how to apply and follow +the GNU GPL, see . + +The GNU General Public License does not permit incorporating your +program into proprietary programs. If your program is a subroutine +library, you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use the +GNU Lesser General Public License instead of this License. But first, +please read . diff --git a/ferveo-python/MANIFEST.in b/ferveo-python/MANIFEST.in new file mode 100644 index 00000000..2dff285a --- /dev/null +++ b/ferveo-python/MANIFEST.in @@ -0,0 +1,4 @@ +include Cargo.toml +include README.md +include LICENSE +recursive-include src * diff --git a/ferveo-python/README.md b/ferveo-python/README.md new file mode 100644 index 00000000..3d067b6b --- /dev/null +++ b/ferveo-python/README.md @@ -0,0 +1,5 @@ +# Python bindings for `ferveo` + +## Build + +You will need to have `setuptools-rust` installed. Then, for development, you can just do `pip install -e .` as usual. diff --git a/ferveo-python/build.rs b/ferveo-python/build.rs new file mode 100644 index 00000000..dace4a9b --- /dev/null +++ b/ferveo-python/build.rs @@ -0,0 +1,3 @@ +fn main() { + pyo3_build_config::add_extension_module_link_args(); +} diff --git a/ferveo-python/ferveo/__init__.py b/ferveo-python/ferveo/__init__.py new file mode 100644 index 00000000..77a421a9 --- /dev/null +++ b/ferveo-python/ferveo/__init__.py @@ -0,0 +1,4 @@ +from ._ferveo import ( + DecryptionShare, + ParticipantPayload +) diff --git a/ferveo-python/ferveo/__init__.pyi b/ferveo-python/ferveo/__init__.pyi new file mode 100644 index 00000000..ed8e880d --- /dev/null +++ b/ferveo-python/ferveo/__init__.pyi @@ -0,0 +1,22 @@ +from typing import Sequence + + +class ExternalValidator: + + # TODO: Add a proper constructor. Currently, breaks `pip install`. + def __init__(self): + ... + + +class PubliclyVerifiableDkg: + + def __init__( + self, + validators: Sequence[ExternalValidator], + me: ExternalValidator, + threshold: int, + shares_num: int, + ): + ... + + diff --git a/ferveo-python/ferveo/py.typed b/ferveo-python/ferveo/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/ferveo-python/pyproject.toml b/ferveo-python/pyproject.toml new file mode 100644 index 00000000..31ffe048 --- /dev/null +++ b/ferveo-python/pyproject.toml @@ -0,0 +1,2 @@ +[build-system] +requires = ["setuptools", "wheel", "setuptools-rust"] diff --git a/ferveo-python/setup.py b/ferveo-python/setup.py new file mode 100644 index 00000000..29d57adc --- /dev/null +++ b/ferveo-python/setup.py @@ -0,0 +1,39 @@ +from setuptools import setup +from setuptools_rust import Binding, RustExtension + +from pathlib import Path +this_directory = Path(__file__).parent +long_description = (this_directory / "README.md").read_text() + +setup( + name="ferveo", + description="Ferveo DKG scheme", + long_description=long_description, + long_description_content_type="text/markdown", + version="0.1.0", + author="Piotr Roslaniec", + author_email="p.roslaniec@gmail.com", + url="https://github.com/nucypher/ferveo/tree/master/ferveo-python", + rust_extensions=[RustExtension( + "ferveo._ferveo", binding=Binding.PyO3, debug=False)], + packages=["ferveo"], + package_data={ + 'ferveo': ['py.typed', '__init__.pyi'], + }, + # rust extensions are not zip safe, just like C-extensions. + zip_safe=False, + classifiers=[ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Natural Language :: English", + "Programming Language :: Rust", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Topic :: Security :: Cryptography", + ], +) diff --git a/ferveo-python/src/lib.rs b/ferveo-python/src/lib.rs new file mode 100644 index 00000000..7b5b6e3d --- /dev/null +++ b/ferveo-python/src/lib.rs @@ -0,0 +1,37 @@ +extern crate alloc; + +use pyo3::prelude::*; + +#[pyclass(module = "ferveo")] +#[derive(Clone, derive_more::From, derive_more::AsRef)] +pub struct ExternalValidator(ferveo::api::ExternalValidator); + +#[pyclass(module = "ferveo")] +#[derive(derive_more::From, derive_more::AsRef)] +pub struct PubliclyVerifiableDkg(ferveo::api::PubliclyVerifiableDkg); + +#[pymethods] +impl PubliclyVerifiableDkg { + #[new] + pub fn new( + validators: Vec, + me: ExternalValidator, + threshold: u32, + shares_num: u32, + ) -> Self { + let validators = validators.into_iter().map(|v| v.0).collect(); + let me = me.0; + Self(ferveo::api::PubliclyVerifiableDkg::new( + validators, me, threshold, shares_num, + )) + } +} + +/// A Python module implemented in Rust. +#[pymodule] +fn _ferveo(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + m.add_class::()?; + + Ok(()) +} diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs new file mode 100644 index 00000000..7f7dca0b --- /dev/null +++ b/ferveo/src/api.rs @@ -0,0 +1,41 @@ +pub type E = ark_bls12_381::Bls12_381; + +#[derive(Clone)] +pub struct ExternalValidator(ferveo_common::ExternalValidator); + +pub struct PubliclyVerifiableDkg(crate::PubliclyVerifiableDkg); + +impl PubliclyVerifiableDkg { + pub fn new( + validators: Vec, + me: ExternalValidator, + // session_keypair: ferveo_common::Keypair, + // tau: u32, + security_threshold: u32, + shares_num: u32, + // retry_after: u32, + ) -> Self { + let validators = validators + .into_iter() + .map(|v| v.0) + .collect::>>(); + let me = me.0; + let params = crate::Params { + tau: 0, + security_threshold, + shares_num, + retry_after: 0, + }; + let session_keypair = ferveo_common::Keypair:: { + decryption_key: ark_ff::UniformRand::rand(&mut ark_std::test_rng()), + }; + let dkg = crate::PubliclyVerifiableDkg::::new( + validators, + params, + &me, + session_keypair, + ) + .unwrap(); + Self(dkg) + } +} diff --git a/ferveo/src/dkg.rs b/ferveo/src/dkg.rs index 93aebf7f..5487e10b 100644 --- a/ferveo/src/dkg.rs +++ b/ferveo/src/dkg.rs @@ -24,6 +24,7 @@ pub use pv::*; // DKG parameters #[derive(Copy, Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] pub struct Params { + // TODO: Do we need tau? Do we need to distinguish between DKG instances using such an identifier? pub tau: u64, pub security_threshold: u32, pub shares_num: u32, diff --git a/ferveo/src/dkg/pv.rs b/ferveo/src/dkg/pv.rs index 358610a1..a57e1290 100644 --- a/ferveo/src/dkg/pv.rs +++ b/ferveo/src/dkg/pv.rs @@ -13,6 +13,7 @@ use std::collections::BTreeMap; pub struct PubliclyVerifiableDkg { pub params: Params, pub pvss_params: PubliclyVerifiableParams, + // TODO: What is session_keypair? pub session_keypair: ferveo_common::Keypair, pub validators: Vec>, pub vss: BTreeMap>, diff --git a/ferveo/src/lib.rs b/ferveo/src/lib.rs index 4bca1dfc..e7af3129 100644 --- a/ferveo/src/lib.rs +++ b/ferveo/src/lib.rs @@ -1,39 +1,32 @@ #![allow(unused_imports)] -pub mod dkg; -pub mod msg; -pub mod vss; - -pub mod primitives; - -use itertools::{izip, zip_eq}; -pub use primitives::*; - -use ferveo_common::Rng; - -use crate::dkg::*; -use crate::msg::*; - +use anyhow::{anyhow, Result}; +use ark_ec::msm::FixedBaseMSM; +use ark_ec::PairingEngine; use ark_ec::{AffineCurve, ProjectiveCurve}; +use ark_ff::PrimeField; use ark_ff::{Field, One, Zero}; use ark_poly::{ polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, EvaluationDomain, }; use ark_std::{end_timer, start_timer}; -use serde::*; +use ferveo_common::Rng; +use itertools::{izip, zip_eq}; +use measure_time::print_time; +use serde::{Deserialize, Serialize}; + +pub mod api; +pub mod dkg; +pub mod msg; +pub mod primitives; +pub mod vss; -use anyhow::{anyhow, Result}; pub use dkg::*; pub use msg::*; +pub use primitives::*; pub use vss::*; -use ark_ec::msm::FixedBaseMSM; -use ark_ec::PairingEngine; -use ark_ff::PrimeField; - -use measure_time::print_time; - #[cfg(test)] mod test_dkg_full { use super::*; diff --git a/tpke-python/src/lib.rs b/tpke-python/src/lib.rs index 0e616760..c1b8d56f 100644 --- a/tpke-python/src/lib.rs +++ b/tpke-python/src/lib.rs @@ -1,8 +1,3 @@ -// Clippy shows false positives in PyO3 methods. -// See https://github.com/rust-lang/rust-clippy/issues/8971 -// Will probably be fixed by Rust 1.65 -#![allow(clippy::borrow_deref_ref)] - extern crate alloc; extern crate group_threshold_cryptography as tpke; From c85ea43d8e2b961aa3871c524c079df04224af4a Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Wed, 1 Feb 2023 18:05:44 +0100 Subject: [PATCH 09/36] remove dependency on block time --- ferveo-python/src/lib.rs | 11 +- ferveo/benches/benchmarks/validity_checks.rs | 1 - ferveo/examples/pvdkg.rs | 1 - ferveo/src/api.rs | 11 +- ferveo/src/dkg.rs | 9 +- ferveo/src/dkg/pv.rs | 116 ------------------- 6 files changed, 13 insertions(+), 136 deletions(-) diff --git a/ferveo-python/src/lib.rs b/ferveo-python/src/lib.rs index 7b5b6e3d..dc1568b5 100644 --- a/ferveo-python/src/lib.rs +++ b/ferveo-python/src/lib.rs @@ -14,15 +14,20 @@ pub struct PubliclyVerifiableDkg(ferveo::api::PubliclyVerifiableDkg); impl PubliclyVerifiableDkg { #[new] pub fn new( + tau: u64, + shares_num: u32, + security_threshold: u32, validators: Vec, me: ExternalValidator, - threshold: u32, - shares_num: u32, ) -> Self { let validators = validators.into_iter().map(|v| v.0).collect(); let me = me.0; Self(ferveo::api::PubliclyVerifiableDkg::new( - validators, me, threshold, shares_num, + tau, + shares_num, + security_threshold, + validators, + me, )) } } diff --git a/ferveo/benches/benchmarks/validity_checks.rs b/ferveo/benches/benchmarks/validity_checks.rs index 19b31c0e..a564ab67 100644 --- a/ferveo/benches/benchmarks/validity_checks.rs +++ b/ferveo/benches/benchmarks/validity_checks.rs @@ -44,7 +44,6 @@ fn setup_dkg( tau: 0, security_threshold: shares_num / 3, shares_num, - retry_after: 1, }, &me, keypairs[validator], diff --git a/ferveo/examples/pvdkg.rs b/ferveo/examples/pvdkg.rs index 82968d1c..be2e92c5 100644 --- a/ferveo/examples/pvdkg.rs +++ b/ferveo/examples/pvdkg.rs @@ -45,7 +45,6 @@ pub fn setup_dkg( tau: 0, security_threshold: shares_num / 3, shares_num, - retry_after: 1, }, &me, keypairs[validator], diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index 7f7dca0b..1b7c6e8e 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -7,13 +7,11 @@ pub struct PubliclyVerifiableDkg(crate::PubliclyVerifiableDkg); impl PubliclyVerifiableDkg { pub fn new( + tau: u64, + shares_num: u32, + security_threshold: u32, validators: Vec, me: ExternalValidator, - // session_keypair: ferveo_common::Keypair, - // tau: u32, - security_threshold: u32, - shares_num: u32, - // retry_after: u32, ) -> Self { let validators = validators .into_iter() @@ -21,10 +19,9 @@ impl PubliclyVerifiableDkg { .collect::>>(); let me = me.0; let params = crate::Params { - tau: 0, + tau, security_threshold, shares_num, - retry_after: 0, }; let session_keypair = ferveo_common::Keypair:: { decryption_key: ark_ff::UniformRand::rand(&mut ark_std::test_rng()), diff --git a/ferveo/src/dkg.rs b/ferveo/src/dkg.rs index 5487e10b..7ccc9e82 100644 --- a/ferveo/src/dkg.rs +++ b/ferveo/src/dkg.rs @@ -24,17 +24,10 @@ pub use pv::*; // DKG parameters #[derive(Copy, Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] pub struct Params { - // TODO: Do we need tau? Do we need to distinguish between DKG instances using such an identifier? + // TODO: Rename to ritual_id? pub tau: u64, pub security_threshold: u32, pub shares_num: u32, - pub retry_after: u32, // TODO: Remove. Not relevant in our scheme. -} - -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum PvssScheduler { - Wait, - Issue, } #[derive(Debug, Clone)] diff --git a/ferveo/src/dkg/pv.rs b/ferveo/src/dkg/pv.rs index a57e1290..b2d6d907 100644 --- a/ferveo/src/dkg/pv.rs +++ b/ferveo/src/dkg/pv.rs @@ -20,7 +20,6 @@ pub struct PubliclyVerifiableDkg { pub domain: ark_poly::Radix2EvaluationDomain, pub state: DkgState, pub me: usize, - pub window: (u32, u32), } impl PubliclyVerifiableDkg { @@ -49,9 +48,6 @@ impl PubliclyVerifiableDkg { let validators = make_validators(validators); - // TODO: Remove my_partition - let my_partition = - params.retry_after * (2 * me as u32 / params.retry_after); Ok(Self { session_keypair, params, @@ -67,38 +63,9 @@ impl PubliclyVerifiableDkg { }, me, validators, - // TODO: Remove window - window: (my_partition, my_partition + params.retry_after), }) } - /// Increment the number of blocks processed since the DKG protocol - /// began if we are still sharing PVSS transcripts. - /// - /// Returns a value indicating if we should issue a PVSS transcript - pub fn increase_block(&mut self) -> PvssScheduler { - match self.state { - DkgState::Sharing { ref mut block, .. } - if !self.vss.contains_key(&(self.me as u32)) => - { - *block += 1; - // if our scheduled window begins, issue PVSS - if self.window.0 + 1 == *block { - PvssScheduler::Issue - } else if &self.window.1 < block { - // reset the window during which we try to get our - // PVSS on chain - *block = self.window.0 + 1; - // reissue PVSS - PvssScheduler::Issue - } else { - PvssScheduler::Wait - } - } - _ => PvssScheduler::Wait, - } - } - /// Create a new PVSS instance within this DKG session, contributing to the final key /// `rng` is a cryptographic random number generator /// Returns a PVSS dealing message to post on-chain @@ -316,7 +283,6 @@ pub(crate) mod test_common { tau: 0, security_threshold, shares_num, - retry_after: 2, }, &me, keypairs[my_index], @@ -387,7 +353,6 @@ mod test_dkg_init { tau: 0, security_threshold: 4, shares_num: 8, - retry_after: 2, }, &ExternalValidator:: { address: "non-existant-validator".into(), @@ -401,16 +366,6 @@ mod test_dkg_init { "could not find this validator in the provided validator set" ) } - - /// Test that the windows of a validator are correctly - /// computed from the `retry_after` param - #[test] - fn test_validator_windows() { - for i in 0..4_u32 { - let dkg = setup_dkg(i as usize); - assert_eq!(dkg.window, (2 * i, 2 * i + 2)); - } - } } /// Test the dealing phase of the DKG @@ -625,77 +580,6 @@ mod test_dealing { assert!(dkg.apply_message(sender, pvss).is_ok()); assert!(matches!(dkg.state, DkgState::Dealt)) } - - /// Check that if a validators window has not arrived, - /// the DKG advises us to wait - #[test] - fn test_pvss_wait_before_window() { - let mut dkg = setup_dkg(1); - if let DkgState::Sharing { block, .. } = dkg.state { - assert!(dkg.window.0 > block); - } else { - panic!("Test failed"); - } - assert_eq!(dkg.increase_block(), PvssScheduler::Wait); - } - - /// Test that the DKG advises us to not issue a PVSS transcript - /// if we are not in state [`DkgState::Sharing{..}`] - #[test] - fn test_pvss_wait_if_not_in_sharing_state() { - let mut dkg = setup_dkg(0); - for state in vec![ - Dealt, - DkgState::Success { - final_key: G1::zero(), - }, - DkgState::Invalid, - ] { - dkg.state = state; - assert_eq!(dkg.increase_block(), PvssScheduler::Wait); - } - } - - /// Test that if we already have our PVSS on chain, - /// the DKG advises us not to issue a new one - #[test] - fn test_pvss_wait_if_already_applied() { - let rng = &mut ark_std::test_rng(); - let mut dkg = setup_dkg(0); - let pvss = dkg.share(rng).expect("Test failed"); - let sender = dkg.validators[0].validator.clone(); - // check that verification fails - assert!(dkg.verify_message(&sender, &pvss).is_ok()); - assert!(dkg.apply_message(sender, pvss).is_ok()); - assert_eq!(dkg.increase_block(), PvssScheduler::Wait); - } - - /// Test that if our own PVSS transcript is not on chain - /// after the retry window, the DKG advises us to issue again. - #[test] - fn test_pvss_reissue() { - let mut dkg = setup_dkg(0); - dkg.state = DkgState::Sharing { - accumulated_shares: 0, - block: 2, - }; - assert_eq!(dkg.increase_block(), PvssScheduler::Issue); - assert_eq!(dkg.increase_block(), PvssScheduler::Wait); - } - - /// Test that we are only advised to issue a PVSS at the - /// beginning of our window, not for every block in it - #[test] - fn test_pvss_wait_middle_of_window() { - let mut dkg = setup_dkg(0); - assert_eq!(dkg.increase_block(), PvssScheduler::Issue); - if let DkgState::Sharing { block, .. } = dkg.state { - assert!(dkg.window.0 < block && block < dkg.window.1); - } else { - panic!("Test failed"); - } - assert_eq!(dkg.increase_block(), PvssScheduler::Wait); - } } /// Test aggregating transcripts into final key From 5ba7451f1ae54995e90570b2e970263124ffa803 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Thu, 2 Feb 2023 15:01:50 +0100 Subject: [PATCH 10/36] sketch the server api --- ferveo-python/src/lib.rs | 89 +++++++++++++++++--- ferveo/benches/benchmarks/validity_checks.rs | 2 +- ferveo/examples/pvdkg.rs | 2 +- ferveo/src/api.rs | 81 +++++++++++++++--- ferveo/src/dkg/common.rs | 2 +- ferveo/src/dkg/pv.rs | 24 ++++-- ferveo/src/vss/pvss.rs | 3 +- tpke-wasm/src/lib.rs | 2 +- tpke/src/api.rs | 11 ++- 9 files changed, 178 insertions(+), 38 deletions(-) diff --git a/ferveo-python/src/lib.rs b/ferveo-python/src/lib.rs index dc1568b5..7ed856ea 100644 --- a/ferveo-python/src/lib.rs +++ b/ferveo-python/src/lib.rs @@ -4,30 +4,89 @@ use pyo3::prelude::*; #[pyclass(module = "ferveo")] #[derive(Clone, derive_more::From, derive_more::AsRef)] -pub struct ExternalValidator(ferveo::api::ExternalValidator); +pub struct Validator(ferveo::api::Validator); + +#[pyclass(module = "ferveo")] +#[derive(Clone, derive_more::From, derive_more::AsRef)] +pub struct Transcript(ferveo::api::Transcript); + +#[derive(FromPyObject)] +pub struct ValidatorMessage(Validator, Transcript); #[pyclass(module = "ferveo")] #[derive(derive_more::From, derive_more::AsRef)] -pub struct PubliclyVerifiableDkg(ferveo::api::PubliclyVerifiableDkg); +pub struct Dkg(ferveo::api::Dkg); #[pymethods] -impl PubliclyVerifiableDkg { +impl Dkg { #[new] pub fn new( tau: u64, shares_num: u32, security_threshold: u32, - validators: Vec, - me: ExternalValidator, + validators: Vec, + me: Validator, ) -> Self { - let validators = validators.into_iter().map(|v| v.0).collect(); - let me = me.0; - Self(ferveo::api::PubliclyVerifiableDkg::new( + let validators: Vec<_> = validators.into_iter().map(|v| v.0).collect(); + Self(ferveo::api::Dkg::new( tau, shares_num, security_threshold, - validators, - me, + &validators, + &me.0, + )) + } + + pub fn generate_transcript(&self) -> Transcript { + Transcript(self.0.generate_transcript()) + } + + pub fn aggregate_transcripts( + &self, + messages: Vec, + ) -> AggregatedTranscript { + let messages = messages + .into_iter() + .map(|message| (message.0 .0, message.1 .0)) + .collect(); + AggregatedTranscript(self.0.aggregate_transcripts(messages)) + } +} + +#[pyclass(module = "ferveo")] +#[derive(derive_more::From, derive_more::AsRef)] +pub struct Ciphertext(ferveo::api::Ciphertext); + +#[pyclass(module = "ferveo")] +#[derive(derive_more::From, derive_more::AsRef)] +pub struct UnblindingKey(ferveo::api::UnblindingKey); + +#[pyclass(module = "ferveo")] +#[derive(derive_more::From, derive_more::AsRef)] +pub struct DecryptionShare(ferveo::api::DecryptionShare); + +#[pyclass(module = "ferveo")] +#[derive(derive_more::From, derive_more::AsRef)] +pub struct AggregatedTranscript(ferveo::api::AggregatedTranscript); + +#[pymethods] +impl AggregatedTranscript { + pub fn validate(&self, dkg: &Dkg) -> bool { + self.0.validate(&dkg.0) + } + + pub fn create_decryption_share( + &self, + dkg: &Dkg, + ciphertext: &Ciphertext, + aad: &[u8], + unblinding_key: &UnblindingKey, + ) -> DecryptionShare { + DecryptionShare(self.0.create_decryption_share( + &dkg.0, + &ciphertext.0, + aad, + &unblinding_key.0, )) } } @@ -35,8 +94,12 @@ impl PubliclyVerifiableDkg { /// A Python module implemented in Rust. #[pymodule] fn _ferveo(_py: Python, m: &PyModule) -> PyResult<()> { - m.add_class::()?; - m.add_class::()?; - + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; Ok(()) } diff --git a/ferveo/benches/benchmarks/validity_checks.rs b/ferveo/benches/benchmarks/validity_checks.rs index a564ab67..c9d6a33d 100644 --- a/ferveo/benches/benchmarks/validity_checks.rs +++ b/ferveo/benches/benchmarks/validity_checks.rs @@ -39,7 +39,7 @@ fn setup_dkg( let validators = gen_validators(&keypairs); let me = validators[validator].clone(); PubliclyVerifiableDkg::new( - validators, + &validators, Params { tau: 0, security_threshold: shares_num / 3, diff --git a/ferveo/examples/pvdkg.rs b/ferveo/examples/pvdkg.rs index be2e92c5..bca8d077 100644 --- a/ferveo/examples/pvdkg.rs +++ b/ferveo/examples/pvdkg.rs @@ -40,7 +40,7 @@ pub fn setup_dkg( let validators = gen_validators(&keypairs); let me = validators[validator].clone(); PubliclyVerifiableDkg::new( - validators, + &validators, Params { tau: 0, security_threshold: shares_num / 3, diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index 1b7c6e8e..be5c1328 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -1,23 +1,31 @@ +use ark_poly::EvaluationDomain; +use group_threshold_cryptography as tpke; +use rand::thread_rng; + pub type E = ark_bls12_381::Bls12_381; #[derive(Clone)] -pub struct ExternalValidator(ferveo_common::ExternalValidator); +pub struct Validator(ferveo_common::ExternalValidator); -pub struct PubliclyVerifiableDkg(crate::PubliclyVerifiableDkg); +#[derive(Clone)] +pub struct Transcript(crate::PubliclyVerifiableSS); -impl PubliclyVerifiableDkg { +#[derive(Clone)] +pub struct Dkg(crate::PubliclyVerifiableDkg); + +impl Dkg { pub fn new( tau: u64, shares_num: u32, security_threshold: u32, - validators: Vec, - me: ExternalValidator, + validators: &[Validator], + me: &Validator, ) -> Self { - let validators = validators - .into_iter() - .map(|v| v.0) + let validators = &validators + .iter() + .map(|v| v.0.clone()) .collect::>>(); - let me = me.0; + let me = &me.0; let params = crate::Params { tau, security_threshold, @@ -29,10 +37,63 @@ impl PubliclyVerifiableDkg { let dkg = crate::PubliclyVerifiableDkg::::new( validators, params, - &me, + me, session_keypair, ) .unwrap(); Self(dkg) } + + pub fn generate_transcript(&self) -> Transcript { + let rng = &mut thread_rng(); + Transcript(self.0.create_share(rng).unwrap()) + } + + pub fn aggregate_transcripts( + &self, + messages: Vec<(Validator, Transcript)>, + ) -> AggregatedTranscript { + // Avoid mutating current state + // TODO: Rewrite `apply_message` to not require mutability after validating this API design + let mut dkg = self.0.clone(); + for (validator, transcript) in messages { + dkg.apply_message(validator.0, crate::Message::Deal(transcript.0)) + .unwrap(); + } + + AggregatedTranscript(crate::pvss::aggregate(&self.0)) + } +} + +pub struct Ciphertext(tpke::api::TpkeCiphertext); + +pub struct UnblindingKey(tpke::api::TpkeUnblindingKey); + +pub struct DecryptionShare(tpke::api::TpkeDecryptionShareSimplePrecomputed); + +pub struct AggregatedTranscript( + crate::PubliclyVerifiableSS, +); + +impl AggregatedTranscript { + pub fn validate(&self, dkg: &Dkg) -> bool { + self.0.verify_full(&dkg.0) + } + + pub fn create_decryption_share( + &self, + dkg: &Dkg, + ciphertext: &Ciphertext, + aad: &[u8], + unblinding_key: &UnblindingKey, + ) -> DecryptionShare { + let domain_points: Vec<_> = dkg.0.domain.elements().collect(); + DecryptionShare(self.0.make_decryption_share_simple_precomputed( + &ciphertext.0, + aad, + &unblinding_key.0, + dkg.0.me, + &domain_points, + )) + } } diff --git a/ferveo/src/dkg/common.rs b/ferveo/src/dkg/common.rs index c519db1b..a96cebbb 100644 --- a/ferveo/src/dkg/common.rs +++ b/ferveo/src/dkg/common.rs @@ -3,7 +3,7 @@ use ferveo_common::ExternalValidator; use itertools::izip; pub fn make_validators( - validators: Vec>, + validators: &[ExternalValidator], ) -> Vec> { validators .iter() diff --git a/ferveo/src/dkg/pv.rs b/ferveo/src/dkg/pv.rs index b2d6d907..07d6cd82 100644 --- a/ferveo/src/dkg/pv.rs +++ b/ferveo/src/dkg/pv.rs @@ -6,10 +6,14 @@ use ark_ff::Field; use ark_serialize::*; use ark_std::{end_timer, start_timer}; use ferveo_common::{ExternalValidator, PublicKey}; +use rand::RngCore; use std::collections::BTreeMap; /// The DKG context that holds all of the local state for participating in the DKG -#[derive(Debug, CanonicalSerialize, CanonicalDeserialize)] +// TODO: Consider removing Clone to avoid accidentally NOT-mutating state. +// Currently, we're assuming that the DKG is only mutated by the owner of the instance. +// Consider removing Clone after finalizing ferveo::api +#[derive(Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] pub struct PubliclyVerifiableDkg { pub params: Params, pub pvss_params: PubliclyVerifiableParams, @@ -30,7 +34,7 @@ impl PubliclyVerifiableDkg { /// `me` the validator creating this instance /// `session_keypair` the keypair for `me` pub fn new( - validators: Vec>, + validators: &[ExternalValidator], params: Params, me: &ExternalValidator, session_keypair: ferveo_common::Keypair, @@ -69,10 +73,10 @@ impl PubliclyVerifiableDkg { /// Create a new PVSS instance within this DKG session, contributing to the final key /// `rng` is a cryptographic random number generator /// Returns a PVSS dealing message to post on-chain - pub fn share(&mut self, rng: &mut R) -> Result> { + pub fn share(&mut self, rng: &mut R) -> Result> { use ark_std::UniformRand; print_time!("PVSS Sharing"); - let vss = Pvss::::new(&E::Fr::rand(rng), self, rng)?; + let vss = self.create_share(rng)?; match self.state { DkgState::Sharing { .. } | DkgState::Dealt => { Ok(Message::Deal(vss)) @@ -83,6 +87,14 @@ impl PubliclyVerifiableDkg { } } + pub fn create_share( + &self, + rng: &mut R, + ) -> Result> { + use ark_std::UniformRand; + Pvss::::new(&E::Fr::rand(rng), self, rng) + } + /// Aggregate all received PVSS messages into a single message, prepared to post on-chain pub fn aggregate(&self) -> Result> { match self.state { @@ -278,7 +290,7 @@ pub(crate) mod test_common { let validators = gen_n_validators(&keypairs, shares_num); let me = validators[my_index].clone(); PubliclyVerifiableDkg::new( - validators, + &validators, Params { tau: 0, security_threshold, @@ -348,7 +360,7 @@ mod test_dkg_init { let keypairs = gen_keypairs(); let keypair = ferveo_common::Keypair::::new(rng); let err = PubliclyVerifiableDkg::::new( - gen_validators(&keypairs), + &gen_validators(&keypairs), Params { tau: 0, security_threshold: 4, diff --git a/ferveo/src/vss/pvss.rs b/ferveo/src/vss/pvss.rs index 5d0a92bf..83ee87b0 100644 --- a/ferveo/src/vss/pvss.rs +++ b/ferveo/src/vss/pvss.rs @@ -14,6 +14,7 @@ use group_threshold_cryptography::{ DecryptionShareSimple, DecryptionShareSimplePrecomputed, PrivateKeyShare, }; use itertools::{zip_eq, Itertools}; +use rand::RngCore; use subproductdomain::fast_multiexp; /// These are the blinded evaluations of shares of a single random polynomial @@ -70,7 +71,7 @@ impl PubliclyVerifiableSS { /// `s`: the secret constant coefficient to share /// `dkg`: the current DKG session /// `rng` a cryptographic random number generator - pub fn new( + pub fn new( s: &E::Fr, dkg: &PubliclyVerifiableDkg, rng: &mut R, diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index 647cb884..3ad5bfb2 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -252,7 +252,7 @@ pub struct SharedSecret(TpkeSharedSecret); #[wasm_bindgen] #[derive(Clone, Debug)] pub struct SharedSecretBuilder { - shares: Vec, + shares: Vec, contexts: Vec, } diff --git a/tpke/src/api.rs b/tpke/src/api.rs index 33fa3597..29bb947f 100644 --- a/tpke/src/api.rs +++ b/tpke/src/api.rs @@ -13,8 +13,11 @@ use std::convert::TryInto; pub type E = ark_bls12_381::Bls12_381; pub type TpkePublicKey = ark_bls12_381::G1Affine; pub type TpkePrivateKey = ark_bls12_381::G2Affine; +pub type TpkeUnblindingKey = ark_bls12_381::Fr; pub type TpkeCiphertext = crate::Ciphertext; -pub type TpkeDecryptionShare = crate::DecryptionShareFast; +pub type TpkeDecryptionShareFast = crate::DecryptionShareFast; +pub type TpkeDecryptionShareSimplePrecomputed = + crate::DecryptionShareSimplePrecomputed; pub type TpkePublicDecryptionContext = crate::PublicDecryptionContextFast; pub type TpkeSharedSecret = ::Fqk; @@ -99,7 +102,7 @@ impl PrivateDecryptionContext { } #[derive(Clone, Debug)] -pub struct DecryptionShare(pub TpkeDecryptionShare); +pub struct DecryptionShare(pub TpkeDecryptionShareFast); impl DecryptionShare { pub fn to_bytes(&self) -> Vec { @@ -107,7 +110,7 @@ impl DecryptionShare { } pub fn from_bytes(bytes: &[u8]) -> Self { - let share = TpkeDecryptionShare::from_bytes(bytes); + let share = TpkeDecryptionShareFast::from_bytes(bytes); Self(share) } } @@ -162,7 +165,7 @@ impl ParticipantPayload { .mul(self.decryption_context.b_inv) .into_affine(); - DecryptionShare(TpkeDecryptionShare { + DecryptionShare(TpkeDecryptionShareFast { decrypter_index: self.decryption_context.decrypter_index, decryption_share, }) From 39f7f39cf618e6c46a809707cfc93bf1aae4e49e Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Mon, 6 Feb 2023 12:04:57 +0100 Subject: [PATCH 11/36] simple tdec on server side --- Cargo.lock | 1 + ferveo-python/Cargo.toml | 1 + ferveo-python/src/lib.rs | 17 ++++- ferveo/benches/bench_main.rs | 3 +- ferveo/src/api.rs | 136 ++++++++++++++++++++++++++++++++--- ferveo/src/dkg/pv.rs | 16 +++++ ferveo/src/lib.rs | 2 + ferveo/src/vss/pvss.rs | 6 +- tpke/src/decryption.rs | 4 +- 9 files changed, 168 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c19b5168..9f92b10b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -944,6 +944,7 @@ dependencies = [ "ferveo", "pyo3", "pyo3-build-config", + "rand 0.8.5", ] [[package]] diff --git a/ferveo-python/Cargo.toml b/ferveo-python/Cargo.toml index d8f14035..18ceeeca 100644 --- a/ferveo-python/Cargo.toml +++ b/ferveo-python/Cargo.toml @@ -11,6 +11,7 @@ crate-type = ["cdylib"] pyo3 = "0.17.3" ferveo = { path = "../ferveo" } derive_more = { version = "0.99", default-features = false, features = ["from", "as_ref"] } +rand = "0.8" [build-dependencies] pyo3-build-config = "*" diff --git a/ferveo-python/src/lib.rs b/ferveo-python/src/lib.rs index 7ed856ea..ac69ca48 100644 --- a/ferveo-python/src/lib.rs +++ b/ferveo-python/src/lib.rs @@ -1,6 +1,7 @@ extern crate alloc; use pyo3::prelude::*; +use rand::thread_rng; #[pyclass(module = "ferveo")] #[derive(Clone, derive_more::From, derive_more::AsRef)] @@ -10,6 +11,10 @@ pub struct Validator(ferveo::api::Validator); #[derive(Clone, derive_more::From, derive_more::AsRef)] pub struct Transcript(ferveo::api::Transcript); +#[pyclass(module = "ferveo")] +#[derive(Clone, derive_more::From, derive_more::AsRef)] +pub struct DkgPublicKey(ferveo::api::DkgPublicKey); + #[derive(FromPyObject)] pub struct ValidatorMessage(Validator, Transcript); @@ -37,15 +42,21 @@ impl Dkg { )) } + pub fn final_key(&self) -> DkgPublicKey { + DkgPublicKey(self.0.final_key()) + } + pub fn generate_transcript(&self) -> Transcript { - Transcript(self.0.generate_transcript()) + let rng = &mut thread_rng(); + Transcript(self.0.generate_transcript(rng)) } pub fn aggregate_transcripts( - &self, + // TODO: Avoid mutating current state + &mut self, messages: Vec, ) -> AggregatedTranscript { - let messages = messages + let messages = &messages .into_iter() .map(|message| (message.0 .0, message.1 .0)) .collect(); diff --git a/ferveo/benches/bench_main.rs b/ferveo/benches/bench_main.rs index a177b183..fbd7c746 100644 --- a/ferveo/benches/bench_main.rs +++ b/ferveo/benches/bench_main.rs @@ -3,7 +3,8 @@ use criterion::criterion_main; mod benchmarks; criterion_main! { - // benchmarks::pairing::micro,//bench_batch_inverse, + // benchmarks::pairing::micro, + // bench_batch_inverse, // benchmarks::pairing::ec, benchmarks::validity_checks::validity_checks, } diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index be5c1328..32d14ad0 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -1,15 +1,19 @@ use ark_poly::EvaluationDomain; use group_threshold_cryptography as tpke; -use rand::thread_rng; +use rand::rngs::StdRng; +use rand::{thread_rng, RngCore}; pub type E = ark_bls12_381::Bls12_381; #[derive(Clone)] pub struct Validator(ferveo_common::ExternalValidator); -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Transcript(crate::PubliclyVerifiableSS); +#[derive(Clone)] +pub struct DkgPublicKey(tpke::api::TpkePublicKey); + #[derive(Clone)] pub struct Dkg(crate::PubliclyVerifiableDkg); @@ -44,20 +48,23 @@ impl Dkg { Self(dkg) } - pub fn generate_transcript(&self) -> Transcript { - let rng = &mut thread_rng(); + pub fn final_key(&self) -> DkgPublicKey { + DkgPublicKey(self.0.final_key()) + } + + pub fn generate_transcript(&self, rng: &mut R) -> Transcript { Transcript(self.0.create_share(rng).unwrap()) } pub fn aggregate_transcripts( - &self, - messages: Vec<(Validator, Transcript)>, + &mut self, + messages: &Vec<(Validator, Transcript)>, ) -> AggregatedTranscript { // Avoid mutating current state - // TODO: Rewrite `apply_message` to not require mutability after validating this API design - let mut dkg = self.0.clone(); + // TODO: Rewrite `deal` to not require mutability after validating this API design for (validator, transcript) in messages { - dkg.apply_message(validator.0, crate::Message::Deal(transcript.0)) + self.0 + .deal(validator.0.clone(), transcript.0.clone()) .unwrap(); } @@ -97,3 +104,114 @@ impl AggregatedTranscript { )) } } + +#[cfg(test)] +mod test_ferveo_api { + use crate::api::{Ciphertext, Dkg, UnblindingKey, Validator}; + use crate::dkg::test_common::{ + gen_n_keypairs, gen_n_validators, setup_dealt_dkg_with_n_validators, + setup_dkg_for_n_validators, + }; + use crate::{aggregate, Message, Params, PubliclyVerifiableDkg}; + use ark_bls12_381::{Bls12_381 as E, Fr, G2Projective}; + use ark_ec::ProjectiveCurve; + use ark_poly::EvaluationDomain; + use ark_serialize::CanonicalSerialize; + use ark_std::UniformRand; + use ferveo_common::PublicKey; + use group_threshold_cryptography as tpke; + use itertools::{iproduct, izip}; + use rand::prelude::StdRng; + use rand::SeedableRng; + use std::collections::HashMap; + use std::fmt::format; + + #[test] + fn test_server_api_simple_tdec_precomputed() { + let rng = &mut StdRng::seed_from_u64(0); + + let tau = 1; + let security_threshold = 3; + let shares_num = 4; + + let validator_keypairs = gen_n_keypairs(shares_num); + let validators = validator_keypairs + .iter() + .enumerate() + .map(|(i, keypair)| { + Validator(ferveo_common::ExternalValidator { + address: format!("validator-{}", i), + public_key: keypair.public(), + }) + }) + .collect::>(); + + // Each validator holds their own DKG instance and generates a transcript every + // every validator, including themselves + let messages: Vec<_> = validators + .iter() + .map(|sender| { + let dkg = Dkg::new( + tau, + shares_num, + security_threshold, + &validators, + sender, + ); + (sender.clone(), dkg.generate_transcript(rng)) + }) + .collect(); + + // Now that every validator holds a dkg instance and a transcript for every other validator, + // every validator can aggregate the transcripts + let me = validators[0].clone(); + let mut dkg = + Dkg::new(tau, shares_num, security_threshold, &validators, &me); + let pvss_aggregated = dkg.aggregate_transcripts(&messages); + + // At this point, any given validator should be able to provide a DKG public key + let public_key = dkg.final_key(); + + // In the meantime, the client creates a ciphertext and decryption request + let msg: &[u8] = "abc".as_bytes(); + let aad: &[u8] = "my-aad".as_bytes(); + let ciphertext = tpke::encrypt::<_, E>(msg, aad, &public_key.0, rng); + + // Having aggregated the transcripts, the validators can now create decryption shares + let decryption_shares: Vec<_> = izip!(&validators, &validator_keypairs) + .map(|(validator, validator_keypair)| { + // Each validator holds their own instance of DKG and creates their own aggregate + let mut dkg = Dkg::new( + tau, + shares_num, + security_threshold, + &validators, + validator, + ); + let aggregate = dkg.aggregate_transcripts(&messages); + assert!(pvss_aggregated.validate(&dkg)); + aggregate.create_decryption_share( + &dkg, + &Ciphertext(ciphertext.clone()), + aad, + &UnblindingKey(validator_keypair.decryption_key), + ) + }) + .collect(); + + // Now, the decryption share can be used to decrypt the ciphertext + // This part is part of the client API + let decryption_shares: Vec<_> = decryption_shares + .iter() + .map(|decryption_share| decryption_share.0.clone()) + .collect(); + + let shared_secret = + tpke::share_combine_simple_precomputed::(&decryption_shares); + + let plaintext = + tpke::decrypt_with_shared_secret(&ciphertext, aad, &shared_secret) + .unwrap(); + assert_eq!(plaintext, msg); + } +} diff --git a/ferveo/src/dkg/pv.rs b/ferveo/src/dkg/pv.rs index 07d6cd82..672cf30c 100644 --- a/ferveo/src/dkg/pv.rs +++ b/ferveo/src/dkg/pv.rs @@ -194,6 +194,7 @@ impl PubliclyVerifiableDkg { } = &mut self.state { *accumulated_shares += 1; + // TODO: Should be `== self.params.shares_num` instead? if *accumulated_shares >= self.params.shares_num - self.params.security_threshold { self.state = DkgState::Dealt; } @@ -212,6 +213,21 @@ impl PubliclyVerifiableDkg { )), } } + + pub fn deal( + &mut self, + sender: ExternalValidator, + pvss: Pvss, + ) -> Result<()> { + // Add the ephemeral public key and pvss transcript + let sender = self + .validators + .iter() + .position(|probe| sender.address == probe.validator.address) + .context("dkg received unknown dealer")?; + self.vss.insert(sender as u32, pvss); + Ok(()) + } } #[derive( diff --git a/ferveo/src/lib.rs b/ferveo/src/lib.rs index e7af3129..36ba9482 100644 --- a/ferveo/src/lib.rs +++ b/ferveo/src/lib.rs @@ -46,6 +46,8 @@ mod test_dkg_full { Ciphertext, DecryptionShareSimple, DecryptionShareSimplePrecomputed, }; use itertools::{zip_eq, Itertools}; + use rand::prelude::StdRng; + use rand::SeedableRng; type Fqk = ::Fqk; diff --git a/ferveo/src/vss/pvss.rs b/ferveo/src/vss/pvss.rs index 83ee87b0..07f692cc 100644 --- a/ferveo/src/vss/pvss.rs +++ b/ferveo/src/vss/pvss.rs @@ -21,11 +21,11 @@ use subproductdomain::fast_multiexp; pub type ShareEncryptions = ::G2Affine; /// Marker struct for unaggregated PVSS transcripts -#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] +#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq)] pub struct Unaggregated; /// Marker struct for aggregated PVSS transcripts -#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] +#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq)] pub struct Aggregated; /// Trait gate used to add extra methods to aggregated PVSS transcripts @@ -50,7 +50,7 @@ pub struct PubliclyVerifiableParams { /// Each validator posts a transcript to the chain. Once enough /// validators have done this (their total voting power exceeds /// 2/3 the total), this will be aggregated into a final key -#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] +#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq)] pub struct PubliclyVerifiableSS { /// Used in Feldman commitment to the VSS polynomial, F = g^{\phi} pub coeffs: Vec, diff --git a/tpke/src/decryption.rs b/tpke/src/decryption.rs index d133b207..f401316f 100644 --- a/tpke/src/decryption.rs +++ b/tpke/src/decryption.rs @@ -36,7 +36,7 @@ impl DecryptionShareFast { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct ValidatorShareChecksum { // TODO: Consider replacing named inner variable with () syntax pub checksum: E::G1Affine, @@ -148,7 +148,7 @@ impl DecryptionShareSimple { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct DecryptionShareSimplePrecomputed { pub decrypter_index: usize, pub decryption_share: E::Fqk, From fd47f97510fad4132712dc58714c19fc0fd0d7e4 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Mon, 6 Feb 2023 16:14:44 +0100 Subject: [PATCH 12/36] add ferveo-python example --- Cargo.lock | 1 + ferveo-common/src/keypair.rs | 3 +- ferveo-common/src/lib.rs | 2 - ferveo-python/Cargo.toml | 3 +- ferveo-python/examples/server_api.py | 70 ++++++++++++++ ferveo-python/ferveo/__init__.py | 12 ++- ferveo-python/ferveo/__init__.pyi | 80 +++++++++++++++- ferveo-python/src/lib.rs | 121 ++++++++++++++++++++++-- ferveo/src/api.rs | 134 +++++++++++++++++++++------ tpke-wasm/src/lib.rs | 5 +- tpke/src/api.rs | 5 +- 11 files changed, 386 insertions(+), 50 deletions(-) create mode 100644 ferveo-python/examples/server_api.py diff --git a/Cargo.lock b/Cargo.lock index 9f92b10b..e5c860e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -942,6 +942,7 @@ version = "0.1.0" dependencies = [ "derive_more", "ferveo", + "group-threshold-cryptography", "pyo3", "pyo3-build-config", "rand 0.8.5", diff --git a/ferveo-common/src/keypair.rs b/ferveo-common/src/keypair.rs index b57a3f1c..8feac538 100644 --- a/ferveo-common/src/keypair.rs +++ b/ferveo-common/src/keypair.rs @@ -3,6 +3,7 @@ use ark_ec::{AffineCurve, ProjectiveCurve}; use ark_serialize::{ CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write, }; +use ark_std::rand::RngCore; use serde::*; #[derive(Copy, Clone, Debug)] @@ -69,7 +70,7 @@ impl Keypair { } /// Creates a new ephemeral session key for participating in the DKG - pub fn new(rng: &mut R) -> Self { + pub fn new(rng: &mut R) -> Self { use ark_std::UniformRand; Self { decryption_key: E::Fr::rand(rng), diff --git a/ferveo-common/src/lib.rs b/ferveo-common/src/lib.rs index 7868a5d6..8ae67b93 100644 --- a/ferveo-common/src/lib.rs +++ b/ferveo-common/src/lib.rs @@ -22,8 +22,6 @@ pub struct Validator { pub share_index: usize, } -impl Rng for ark_std::rand::prelude::StdRng {} - pub trait Rng: ark_std::rand::CryptoRng + ark_std::rand::RngCore {} pub mod ark_serde { diff --git a/ferveo-python/Cargo.toml b/ferveo-python/Cargo.toml index 18ceeeca..6b303b83 100644 --- a/ferveo-python/Cargo.toml +++ b/ferveo-python/Cargo.toml @@ -8,8 +8,9 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -pyo3 = "0.17.3" +pyo3 = { version = "0.17.3", features = ["macros"] } ferveo = { path = "../ferveo" } +group-threshold-cryptography = { path = "../tpke" } derive_more = { version = "0.99", default-features = false, features = ["from", "as_ref"] } rand = "0.8" diff --git a/ferveo-python/examples/server_api.py b/ferveo-python/examples/server_api.py new file mode 100644 index 00000000..2b9e4c14 --- /dev/null +++ b/ferveo-python/examples/server_api.py @@ -0,0 +1,70 @@ +from ferveo import ( + encrypt, + combine_decryption_shares, + decrypt_with_shared_secret, + Keypair, + PublicKey, + ExternalValidator, + Transcript, + Dkg, + Ciphertext, + UnblindingKey, + DecryptionShare, + AggregatedTranscript, +) + +tau = 1 +security_threshold = 3 +shares_num = 4 +validator_keypairs = [Keypair.random() for _ in range(0, shares_num)] +validators = [ + ExternalValidator(f"validator-{i}", keypair.public_key) + for i, keypair in enumerate(validator_keypairs) +] +me = validators[0] + +messages = [] +for sender in validators: + dkg = Dkg( + tau=tau, + shares_num=shares_num, + security_threshold=security_threshold, + validators=validators, + me=sender, + ) + messages.append((sender, dkg.generate_transcript())) + +dkg = Dkg( + tau=tau, + shares_num=shares_num, + security_threshold=security_threshold, + validators=validators, + me=me, +) +pvss_aggregated = dkg.aggregate_transcripts(messages) +assert pvss_aggregated.validate(dkg) + +msg = "abc".encode() +aad = "my-aad".encode() +ciphertext = encrypt(msg, aad, dkg.final_key) + +decryption_shares = [] +for validator, validator_keypair in zip(validators, validator_keypairs): + dkg = Dkg( + tau=tau, + shares_num=shares_num, + security_threshold=security_threshold, + validators=validators, + me=validator, + ) + aggregate = dkg.aggregate_transcripts(messages) + assert pvss_aggregated.validate(dkg) + decryption_share = aggregate.create_decryption_share( + dkg, ciphertext, aad, validator_keypair + ) + decryption_shares.append(decryption_share) + +shared_secret = combine_decryption_shares(decryption_shares) + +plaintext = decrypt_with_shared_secret(ciphertext, aad, shared_secret) +assert bytes(plaintext) == msg diff --git a/ferveo-python/ferveo/__init__.py b/ferveo-python/ferveo/__init__.py index 77a421a9..a1c8e436 100644 --- a/ferveo-python/ferveo/__init__.py +++ b/ferveo-python/ferveo/__init__.py @@ -1,4 +1,14 @@ from ._ferveo import ( + encrypt, + combine_decryption_shares, + decrypt_with_shared_secret, + Keypair, + PublicKey, + ExternalValidator, + Transcript, + Dkg, + Ciphertext, + UnblindingKey, DecryptionShare, - ParticipantPayload + AggregatedTranscript, ) diff --git a/ferveo-python/ferveo/__init__.pyi b/ferveo-python/ferveo/__init__.pyi index ed8e880d..4f9fd157 100644 --- a/ferveo-python/ferveo/__init__.pyi +++ b/ferveo-python/ferveo/__init__.pyi @@ -1,22 +1,92 @@ from typing import Sequence +class Keypair: + @staticmethod + def random() -> Keypair: + ... + + @staticmethod + def from_bytes(data: bytes) -> PublicKey: + ... + + def __bytes__(self) -> bytes: + ... + + public_key: PublicKey + + +class PublicKey: + @staticmethod + def from_bytes(data: bytes) -> PublicKey: + ... + + def __bytes__(self) -> bytes: + ... + + +class Validator: + ... + + class ExternalValidator: - # TODO: Add a proper constructor. Currently, breaks `pip install`. - def __init__(self): + def __init__(self, address: str, public_key: PublicKey): ... -class PubliclyVerifiableDkg: +class Transcript: + ... + + +class DkgPublicKey: + ... + + +class ExternalValidatorMessage: + ... + + +class Dkg: def __init__( self, + tau: int, + shares_num: int, + security_threshold: int, validators: Sequence[ExternalValidator], me: ExternalValidator, - threshold: int, - shares_num: int, ): ... + final_key: DkgPublicKey + + def generate_transcript(self) -> Transcript: + ... + + def aggregate_transcripts(self, transcripts: Sequence[(ExternalValidator, Transcript)]) -> Transcript: + ... + +class Ciphertext: + ... + + +class UnblindingKey: + ... + + +class DecryptionShare: + ... + + +class AggregatedTranscript: + + def create_decryption_share( + self, + dkg: Dkg, + ciphertext: Ciphertext, + aad: bytes, + unblinding_key: UnblindingKey + ) -> DecryptionShare: + ... diff --git a/ferveo-python/src/lib.rs b/ferveo-python/src/lib.rs index ac69ca48..7b90b6b9 100644 --- a/ferveo-python/src/lib.rs +++ b/ferveo-python/src/lib.rs @@ -3,20 +3,117 @@ extern crate alloc; use pyo3::prelude::*; use rand::thread_rng; +#[pyfunction] +pub fn encrypt( + message: &[u8], + aad: &[u8], + public_key: &DkgPublicKey, +) -> Ciphertext { + Ciphertext(ferveo::api::encrypt(message, aad, &public_key.0)) +} + +#[pyfunction] +pub fn combine_decryption_shares(shares: Vec) -> SharedSecret { + let shares = shares + .iter() + .map(|share| share.0.clone()) + .collect::>(); + SharedSecret(ferveo::api::combine_decryption_shares(&shares)) +} + +#[pyfunction] +pub fn decrypt_with_shared_secret( + ciphertext: &Ciphertext, + aad: &[u8], + shared_secret: &SharedSecret, +) -> Vec { + ferveo::api::decrypt_with_shared_secret( + &ciphertext.0, + aad, + &shared_secret.0, + ) +} + +#[pyclass(module = "ferveo")] +#[derive(derive_more::From, derive_more::AsRef)] +pub struct SharedSecret(ferveo::api::SharedSecret); + +#[pyclass(module = "ferveo")] +#[derive(derive_more::From, derive_more::AsRef)] +pub struct Keypair(ferveo::api::Keypair); + +#[pymethods] +impl Keypair { + #[staticmethod] + pub fn random() -> Self { + Self(ferveo::api::Keypair::random(&mut thread_rng())) + } + + #[staticmethod] + pub fn from_bytes(bytes: &[u8]) -> Self { + Self(ferveo::api::Keypair::from_bytes(bytes)) + } + + fn __bytes__(&self) -> Vec { + self.0.to_bytes() + } + + #[getter] + pub fn public_key(&self) -> PublicKey { + PublicKey(self.0.public_key()) + } +} + #[pyclass(module = "ferveo")] #[derive(Clone, derive_more::From, derive_more::AsRef)] -pub struct Validator(ferveo::api::Validator); +pub struct PublicKey(ferveo::api::PublicKey); + +#[pymethods] +impl PublicKey { + #[staticmethod] + pub fn from_bytes(bytes: &[u8]) -> Self { + Self(ferveo::api::PublicKey::from_bytes(bytes)) + } + + pub fn to_bytes(&self) -> Vec { + self.0.to_bytes() + } +} + +#[pyclass(module = "ferveo")] +#[derive(Clone, derive_more::From, derive_more::AsRef)] +pub struct ExternalValidator(ferveo::api::ExternalValidator); + +#[pymethods] +impl ExternalValidator { + #[new] + pub fn new(address: String, public_key: PublicKey) -> Self { + Self(ferveo::api::ExternalValidator::new(address, public_key.0)) + } +} #[pyclass(module = "ferveo")] #[derive(Clone, derive_more::From, derive_more::AsRef)] pub struct Transcript(ferveo::api::Transcript); +#[pymethods] +impl Transcript { + #[staticmethod] + pub fn from_bytes(bytes: &[u8]) -> Self { + Self(ferveo::api::Transcript::from_bytes(bytes)) + } + + pub fn to_bytes(&self) -> Vec { + self.0.to_bytes() + } +} + #[pyclass(module = "ferveo")] #[derive(Clone, derive_more::From, derive_more::AsRef)] pub struct DkgPublicKey(ferveo::api::DkgPublicKey); #[derive(FromPyObject)] -pub struct ValidatorMessage(Validator, Transcript); +pub struct ExternalValidatorMessage(ExternalValidator, Transcript); #[pyclass(module = "ferveo")] #[derive(derive_more::From, derive_more::AsRef)] @@ -29,8 +126,8 @@ impl Dkg { tau: u64, shares_num: u32, security_threshold: u32, - validators: Vec, - me: Validator, + validators: Vec, + me: ExternalValidator, ) -> Self { let validators: Vec<_> = validators.into_iter().map(|v| v.0).collect(); Self(ferveo::api::Dkg::new( @@ -42,6 +139,7 @@ impl Dkg { )) } + #[getter] pub fn final_key(&self) -> DkgPublicKey { DkgPublicKey(self.0.final_key()) } @@ -54,7 +152,7 @@ impl Dkg { pub fn aggregate_transcripts( // TODO: Avoid mutating current state &mut self, - messages: Vec, + messages: Vec, ) -> AggregatedTranscript { let messages = &messages .into_iter() @@ -73,7 +171,7 @@ pub struct Ciphertext(ferveo::api::Ciphertext); pub struct UnblindingKey(ferveo::api::UnblindingKey); #[pyclass(module = "ferveo")] -#[derive(derive_more::From, derive_more::AsRef)] +#[derive(Clone, derive_more::AsRef, derive_more::From)] pub struct DecryptionShare(ferveo::api::DecryptionShare); #[pyclass(module = "ferveo")] @@ -91,13 +189,13 @@ impl AggregatedTranscript { dkg: &Dkg, ciphertext: &Ciphertext, aad: &[u8], - unblinding_key: &UnblindingKey, + validator_keypair: &Keypair, ) -> DecryptionShare { DecryptionShare(self.0.create_decryption_share( &dkg.0, &ciphertext.0, aad, - &unblinding_key.0, + &validator_keypair.0, )) } } @@ -105,7 +203,12 @@ impl AggregatedTranscript { /// A Python module implemented in Rust. #[pymodule] fn _ferveo(_py: Python, m: &PyModule) -> PyResult<()> { - m.add_class::()?; + m.add_function(wrap_pyfunction!(encrypt, m)?)?; + m.add_function(wrap_pyfunction!(combine_decryption_shares, m)?)?; + m.add_function(wrap_pyfunction!(decrypt_with_shared_secret, m)?)?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index 32d14ad0..f13a913c 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -1,18 +1,107 @@ use ark_poly::EvaluationDomain; +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use bincode::Options; use group_threshold_cryptography as tpke; use rand::rngs::StdRng; -use rand::{thread_rng, RngCore}; +use rand::{thread_rng, RngCore, SeedableRng}; pub type E = ark_bls12_381::Bls12_381; +pub fn encrypt( + message: &[u8], + aad: &[u8], + public_key: &DkgPublicKey, +) -> Ciphertext { + Ciphertext(tpke::api::encrypt(message, aad, &public_key.0)) +} + +pub fn combine_decryption_shares( + decryption_shares: &[DecryptionShare], +) -> SharedSecret { + let shares = decryption_shares + .iter() + .map(|share| share.0.clone()) + .collect::>(); + SharedSecret(tpke::share_combine_simple_precomputed::(&shares)) +} + +pub fn decrypt_with_shared_secret( + ciphertext: &Ciphertext, + aad: &[u8], + shared_secret: &SharedSecret, +) -> Vec { + tpke::decrypt_with_shared_secret(&ciphertext.0, aad, &shared_secret.0) + .unwrap() +} + +pub struct SharedSecret(tpke::api::TpkeSharedSecret); + +pub struct Keypair(ferveo_common::Keypair); + +impl Keypair { + pub fn random(rng: &mut R) -> Self { + Self(ferveo_common::Keypair::::new(rng)) + } + + pub fn public_key(&self) -> PublicKey { + PublicKey(self.0.public()) + } + + pub fn from_bytes(bytes: &[u8]) -> Self { + Self(ferveo_common::Keypair::::deserialize(bytes).unwrap()) + } + + pub fn to_bytes(&self) -> Vec { + let mut buf = vec![]; + self.0.serialize(&mut buf).unwrap(); + buf + } +} + +#[derive(Clone)] +pub struct PublicKey(ferveo_common::PublicKey); + +impl PublicKey { + pub fn from_bytes(bytes: &[u8]) -> Self { + Self(ferveo_common::PublicKey::::deserialize(bytes).unwrap()) + } + + pub fn to_bytes(&self) -> Vec { + let mut buf = vec![]; + self.0.serialize(&mut buf).unwrap(); + buf + } +} + #[derive(Clone)] -pub struct Validator(ferveo_common::ExternalValidator); +pub struct ExternalValidator(ferveo_common::ExternalValidator); + +impl ExternalValidator { + pub fn new(address: String, public_key: PublicKey) -> Self { + Self(ferveo_common::ExternalValidator { + address, + public_key: public_key.0, + }) + } +} #[derive(Clone, Debug)] pub struct Transcript(crate::PubliclyVerifiableSS); +impl Transcript { + pub fn from_bytes(bytes: &[u8]) -> Self { + Self(crate::PubliclyVerifiableSS::::deserialize(bytes).unwrap()) + } + + pub fn to_bytes(&self) -> Vec { + let mut buf = vec![]; + self.0.serialize(&mut buf).unwrap(); + buf + } +} + #[derive(Clone)] -pub struct DkgPublicKey(tpke::api::TpkePublicKey); +pub struct DkgPublicKey(pub tpke::api::TpkeDkgPublicKey); #[derive(Clone)] pub struct Dkg(crate::PubliclyVerifiableDkg); @@ -22,8 +111,8 @@ impl Dkg { tau: u64, shares_num: u32, security_threshold: u32, - validators: &[Validator], - me: &Validator, + validators: &[ExternalValidator], + me: &ExternalValidator, ) -> Self { let validators = &validators .iter() @@ -58,7 +147,7 @@ impl Dkg { pub fn aggregate_transcripts( &mut self, - messages: &Vec<(Validator, Transcript)>, + messages: &Vec<(ExternalValidator, Transcript)>, ) -> AggregatedTranscript { // Avoid mutating current state // TODO: Rewrite `deal` to not require mutability after validating this API design @@ -72,10 +161,11 @@ impl Dkg { } } -pub struct Ciphertext(tpke::api::TpkeCiphertext); +pub struct Ciphertext(pub tpke::api::TpkeCiphertext); pub struct UnblindingKey(tpke::api::TpkeUnblindingKey); +#[derive(Clone)] pub struct DecryptionShare(tpke::api::TpkeDecryptionShareSimplePrecomputed); pub struct AggregatedTranscript( @@ -92,13 +182,13 @@ impl AggregatedTranscript { dkg: &Dkg, ciphertext: &Ciphertext, aad: &[u8], - unblinding_key: &UnblindingKey, + validator_keypair: &Keypair, ) -> DecryptionShare { let domain_points: Vec<_> = dkg.0.domain.elements().collect(); DecryptionShare(self.0.make_decryption_share_simple_precomputed( &ciphertext.0, aad, - &unblinding_key.0, + &validator_keypair.0.decryption_key, dkg.0.me, &domain_points, )) @@ -107,12 +197,8 @@ impl AggregatedTranscript { #[cfg(test)] mod test_ferveo_api { - use crate::api::{Ciphertext, Dkg, UnblindingKey, Validator}; - use crate::dkg::test_common::{ - gen_n_keypairs, gen_n_validators, setup_dealt_dkg_with_n_validators, - setup_dkg_for_n_validators, - }; - use crate::{aggregate, Message, Params, PubliclyVerifiableDkg}; + use crate::api::*; + use crate::dkg::test_common::*; use ark_bls12_381::{Bls12_381 as E, Fr, G2Projective}; use ark_ec::ProjectiveCurve; use ark_poly::EvaluationDomain; @@ -139,7 +225,7 @@ mod test_ferveo_api { .iter() .enumerate() .map(|(i, keypair)| { - Validator(ferveo_common::ExternalValidator { + ExternalValidator(ferveo_common::ExternalValidator { address: format!("validator-{}", i), public_key: keypair.public(), }) @@ -175,7 +261,7 @@ mod test_ferveo_api { // In the meantime, the client creates a ciphertext and decryption request let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); - let ciphertext = tpke::encrypt::<_, E>(msg, aad, &public_key.0, rng); + let ciphertext = encrypt(msg, aad, &public_key); // Having aggregated the transcripts, the validators can now create decryption shares let decryption_shares: Vec<_> = izip!(&validators, &validator_keypairs) @@ -192,26 +278,20 @@ mod test_ferveo_api { assert!(pvss_aggregated.validate(&dkg)); aggregate.create_decryption_share( &dkg, - &Ciphertext(ciphertext.clone()), + &ciphertext, aad, - &UnblindingKey(validator_keypair.decryption_key), + &Keypair(*validator_keypair), ) }) .collect(); // Now, the decryption share can be used to decrypt the ciphertext // This part is part of the client API - let decryption_shares: Vec<_> = decryption_shares - .iter() - .map(|decryption_share| decryption_share.0.clone()) - .collect(); - let shared_secret = - tpke::share_combine_simple_precomputed::(&decryption_shares); + let shared_secret = combine_decryption_shares(&decryption_shares); let plaintext = - tpke::decrypt_with_shared_secret(&ciphertext, aad, &shared_secret) - .unwrap(); + decrypt_with_shared_secret(&ciphertext, aad, &shared_secret); assert_eq!(plaintext, msg); } } diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index 3ad5bfb2..e85d37d3 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -101,7 +101,7 @@ impl ParticipantPayload { #[wasm_bindgen] #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct PublicKey( - #[serde_as(as = "tpke::serialization::SerdeAs")] pub(crate) TpkePublicKey, + #[serde_as(as = "tpke::serialization::SerdeAs")] pub(crate) TpkeDkgPublicKey, ); #[wasm_bindgen] @@ -109,7 +109,8 @@ impl PublicKey { #[wasm_bindgen] pub fn from_bytes(bytes: &[u8]) -> Self { let mut reader = bytes; - let pk = TpkePublicKey::deserialize_uncompressed(&mut reader).unwrap(); + let pk = + TpkeDkgPublicKey::deserialize_uncompressed(&mut reader).unwrap(); PublicKey(pk) } diff --git a/tpke/src/api.rs b/tpke/src/api.rs index 29bb947f..18fa4e09 100644 --- a/tpke/src/api.rs +++ b/tpke/src/api.rs @@ -11,7 +11,7 @@ use std::convert::TryInto; // Fixing some of the types here on our target engine // TODO: Consider fixing on crate::api level instead of bindings level pub type E = ark_bls12_381::Bls12_381; -pub type TpkePublicKey = ark_bls12_381::G1Affine; +pub type TpkeDkgPublicKey = ark_bls12_381::G1Affine; pub type TpkePrivateKey = ark_bls12_381::G2Affine; pub type TpkeUnblindingKey = ark_bls12_381::Fr; pub type TpkeCiphertext = crate::Ciphertext; @@ -26,8 +26,9 @@ pub type TpkeResult = crate::Result; pub fn encrypt( message: &[u8], aad: &[u8], - pubkey: &TpkePublicKey, + pubkey: &TpkeDkgPublicKey, ) -> TpkeCiphertext { + // TODO: Should rng be a parameter? let rng = &mut rand::thread_rng(); crate::encrypt(message, aad, pubkey, rng) } From 81ea692b10493f81720431750a99392eefba43f3 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Tue, 7 Feb 2023 10:31:07 +0100 Subject: [PATCH 13/36] support server-side persistance --- ferveo-python/examples/server_api.py | 18 +++++++++++++++++- ferveo-python/src/lib.rs | 26 ++++++++++++++++++++------ ferveo/src/api.rs | 15 +++++++++++++++ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/ferveo-python/examples/server_api.py b/ferveo-python/examples/server_api.py index 2b9e4c14..9d47695a 100644 --- a/ferveo-python/examples/server_api.py +++ b/ferveo-python/examples/server_api.py @@ -21,8 +21,9 @@ ExternalValidator(f"validator-{i}", keypair.public_key) for i, keypair in enumerate(validator_keypairs) ] -me = validators[0] +# Each validator holds their own DKG instance and generates a transcript every +# validator, including themselves messages = [] for sender in validators: dkg = Dkg( @@ -34,6 +35,9 @@ ) messages.append((sender, dkg.generate_transcript())) +# Now that every validator holds a dkg instance and a transcript for every other validator, +# every validator can aggregate the transcripts +me = validators[0] dkg = Dkg( tau=tau, shares_num=shares_num, @@ -44,10 +48,19 @@ pvss_aggregated = dkg.aggregate_transcripts(messages) assert pvss_aggregated.validate(dkg) +# Server can persist transcript and the aggregated transcript +transcripts_ser = [bytes(transcript) for _, transcript in messages] +transcripts_deser = [Transcript.from_bytes(t) for t in transcripts_ser] + +agg_transcript_ser = bytes(pvss_aggregated) +agg_transcript_deser = AggregatedTranscript.from_bytes(agg_transcript_ser) + +# In the meantime, the client creates a ciphertext and decryption request msg = "abc".encode() aad = "my-aad".encode() ciphertext = encrypt(msg, aad, dkg.final_key) +# Having aggregated the transcripts, the validators can now create decryption shares decryption_shares = [] for validator, validator_keypair in zip(validators, validator_keypairs): dkg = Dkg( @@ -64,6 +77,9 @@ ) decryption_shares.append(decryption_share) +# Now, the decryption share can be used to decrypt the ciphertext +# This part is part of the client API + shared_secret = combine_decryption_shares(decryption_shares) plaintext = decrypt_with_shared_secret(ciphertext, aad, shared_secret) diff --git a/ferveo-python/src/lib.rs b/ferveo-python/src/lib.rs index 7b90b6b9..410a96f3 100644 --- a/ferveo-python/src/lib.rs +++ b/ferveo-python/src/lib.rs @@ -1,6 +1,7 @@ extern crate alloc; use pyo3::prelude::*; +use pyo3::types::PyBytes; use rand::thread_rng; #[pyfunction] @@ -54,8 +55,9 @@ impl Keypair { Self(ferveo::api::Keypair::from_bytes(bytes)) } - fn __bytes__(&self) -> Vec { - self.0.to_bytes() + fn __bytes__(&self) -> PyObject { + let serialized = self.0.to_bytes(); + Python::with_gil(|py| PyBytes::new(py, &serialized).into()) } #[getter] @@ -75,8 +77,9 @@ impl PublicKey { Self(ferveo::api::PublicKey::from_bytes(bytes)) } - pub fn to_bytes(&self) -> Vec { - self.0.to_bytes() + fn __bytes__(&self) -> PyObject { + let serialized = self.0.to_bytes(); + Python::with_gil(|py| PyBytes::new(py, &serialized).into()) } } @@ -103,8 +106,9 @@ impl Transcript { Self(ferveo::api::Transcript::from_bytes(bytes)) } - pub fn to_bytes(&self) -> Vec { - self.0.to_bytes() + fn __bytes__(&self) -> PyObject { + let serialized = self.0.to_bytes(); + Python::with_gil(|py| PyBytes::new(py, &serialized).into()) } } @@ -198,6 +202,16 @@ impl AggregatedTranscript { &validator_keypair.0, )) } + + #[staticmethod] + pub fn from_bytes(bytes: &[u8]) -> Self { + Self(ferveo::api::AggregatedTranscript::from_bytes(bytes)) + } + + fn __bytes__(&self) -> PyObject { + let serialized = self.0.to_bytes(); + Python::with_gil(|py| PyBytes::new(py, &serialized).into()) + } } /// A Python module implemented in Rust. diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index f13a913c..23f775d2 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -193,6 +193,21 @@ impl AggregatedTranscript { &domain_points, )) } + + pub fn from_bytes(bytes: &[u8]) -> Self { + Self( + crate::PubliclyVerifiableSS::::deserialize( + bytes, + ) + .unwrap(), + ) + } + + pub fn to_bytes(&self) -> Vec { + let mut buf = vec![]; + self.0.serialize(&mut buf).unwrap(); + buf + } } #[cfg(test)] From 7257843a9722f4a63bfbe82fcfbaf2088711dfb6 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Thu, 9 Feb 2023 10:13:51 +0100 Subject: [PATCH 14/36] simple tdec on client side fails --- Cargo.lock | 1 - ferveo-common/src/lib.rs | 5 +- ferveo/src/api.rs | 8 +- tpke-python/src/lib.rs | 16 --- tpke-wasm/Cargo.toml | 5 - tpke-wasm/benches/benchmarks.rs | 72 ----------- tpke-wasm/src/lib.rs | 206 +++++--------------------------- tpke-wasm/src/test.rs | 41 +++++++ tpke-wasm/tests/node.rs | 133 ++++++++------------- tpke/src/api.rs | 153 ++++-------------------- tpke/src/ciphertext.rs | 21 ++-- tpke/src/decryption.rs | 53 +++++++- 12 files changed, 222 insertions(+), 492 deletions(-) delete mode 100644 tpke-wasm/benches/benchmarks.rs create mode 100644 tpke-wasm/src/test.rs diff --git a/Cargo.lock b/Cargo.lock index e5c860e8..2dbbc9c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2174,7 +2174,6 @@ dependencies = [ "ark-std", "bincode", "console_error_panic_hook", - "criterion 0.4.0", "getrandom 0.2.7", "group-threshold-cryptography", "js-sys", diff --git a/ferveo-common/src/lib.rs b/ferveo-common/src/lib.rs index 8ae67b93..ab4c3329 100644 --- a/ferveo-common/src/lib.rs +++ b/ferveo-common/src/lib.rs @@ -54,13 +54,16 @@ pub mod ark_serde { #[test] fn test_ark_serde() { use ark_bls12_381::G1Affine; + use ark_ec::AffineCurve; + use serde::{Deserialize, Serialize}; + #[derive(Serialize, Deserialize)] struct Test { #[serde(with = "ark_serde")] pub p: G1Affine, } - use ark_ec::AffineCurve; + let p = G1Affine::prime_subgroup_generator(); let t = Test { p }; let m = serde_json::to_string(&t).unwrap(); diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index 23f775d2..cebc3e51 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -30,7 +30,7 @@ pub fn decrypt_with_shared_secret( aad: &[u8], shared_secret: &SharedSecret, ) -> Vec { - tpke::decrypt_with_shared_secret(&ciphertext.0, aad, &shared_secret.0) + tpke::api::decrypt_with_shared_secret(&ciphertext.0, aad, &shared_secret.0) .unwrap() } @@ -161,12 +161,12 @@ impl Dkg { } } -pub struct Ciphertext(pub tpke::api::TpkeCiphertext); +pub struct Ciphertext(pub tpke::api::Ciphertext); pub struct UnblindingKey(tpke::api::TpkeUnblindingKey); #[derive(Clone)] -pub struct DecryptionShare(tpke::api::TpkeDecryptionShareSimplePrecomputed); +pub struct DecryptionShare(tpke::api::TpkeDecryptionShare); pub struct AggregatedTranscript( crate::PubliclyVerifiableSS, @@ -186,7 +186,7 @@ impl AggregatedTranscript { ) -> DecryptionShare { let domain_points: Vec<_> = dkg.0.domain.elements().collect(); DecryptionShare(self.0.make_decryption_share_simple_precomputed( - &ciphertext.0, + &ciphertext.0 .0, aad, &validator_keypair.0.decryption_key, dkg.0.me, diff --git a/tpke-python/src/lib.rs b/tpke-python/src/lib.rs index c1b8d56f..130e7203 100644 --- a/tpke-python/src/lib.rs +++ b/tpke-python/src/lib.rs @@ -16,26 +16,10 @@ impl DecryptionShare { } } -#[pyclass(module = "tpke")] -pub struct ParticipantPayload(tpke::api::ParticipantPayload); - -#[pymethods] -impl ParticipantPayload { - #[staticmethod] - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(tpke::api::ParticipantPayload::from_bytes(bytes)) - } - - pub fn to_decryption_share(&self) -> DecryptionShare { - DecryptionShare(self.0.to_decryption_share()) - } -} - /// A Python module implemented in Rust. #[pymodule] fn _tpke(_py: Python, m: &PyModule) -> PyResult<()> { m.add_class::()?; - m.add_class::()?; Ok(()) } diff --git a/tpke-wasm/Cargo.toml b/tpke-wasm/Cargo.toml index 9eab8584..04ec5a3e 100644 --- a/tpke-wasm/Cargo.toml +++ b/tpke-wasm/Cargo.toml @@ -33,9 +33,4 @@ ark-std = "0.3.0" [dev-dependencies] wasm-bindgen-test = "0.3.13" console_error_panic_hook = "0.1.7" -criterion = { version = "0.4", default-features = false } rand_core = "0.6" - -[[bench]] -name = "benchmarks" -harness = false \ No newline at end of file diff --git a/tpke-wasm/benches/benchmarks.rs b/tpke-wasm/benches/benchmarks.rs deleted file mode 100644 index 6c0893e5..00000000 --- a/tpke-wasm/benches/benchmarks.rs +++ /dev/null @@ -1,72 +0,0 @@ -#![allow(clippy::redundant_closure)] - -use criterion::{black_box, criterion_group, criterion_main, Criterion}; - -pub fn bench_encrypt_combine(c: &mut Criterion) { - use tpke_wasm::*; - - fn bench_encrypt(num_shares: usize, threshold: usize) -> impl Fn() { - let message = "my-secret-message".as_bytes().to_vec(); - let aad = "my-aad".as_bytes().to_vec(); - let setup = Setup::new(threshold, num_shares); - move || { - let message = message.clone(); - let aad = aad.clone(); - black_box(encrypt(&message, &aad, &setup.public_key)); - } - } - - fn bench_combine(num_shares: usize, threshold: usize) -> impl Fn() { - let message = "my-secret-message".as_bytes().to_vec(); - let aad = "my-aad".as_bytes().to_vec(); - let setup = Setup::new(threshold, num_shares); - let ciphertext = encrypt(&message.to_vec(), &aad, &setup.public_key); - let participant_payloads: Vec = setup - .decrypter_indexes() - .iter() - .map(|index| { - ParticipantPayload::new( - &setup.private_context_at(*index), - &ciphertext.clone(), - ) - }) - .collect(); - let decryption_shares: Vec = participant_payloads - .iter() - .map(|p| p.to_decryption_share()) - .collect(); - - move || { - let setup = setup.clone(); - let decryption_shares = decryption_shares.clone(); - #[allow(clippy::unit_arg)] - black_box({ - let mut ss_builder = SharedSecretBuilder::new(&setup); - for share in decryption_shares { - ss_builder.add_decryption_share(&share); - } - ss_builder.build(&ciphertext); - }) - } - } - - let mut group = c.benchmark_group("TPKE-WASM"); - group.sample_size(10); - - for num_shares in [8, 16, 32, 64, 128].iter() { - let encrypt_fn = bench_encrypt(*num_shares, *num_shares); - group.measurement_time(core::time::Duration::new(45, 0)); - group.bench_function(format!("tpke-wasm::encrypt - num_shares={}, num_entities={}, threshold={}", num_shares, num_shares, num_shares), |b| { - b.iter(|| encrypt_fn()) - }); - - let combine_fn = bench_combine(*num_shares, *num_shares); - group.measurement_time(core::time::Duration::new(45, 0)); - group.bench_function(format!("tpke-wasm::combine - num_shares={}, num_entities={}, threshold={}", num_shares, num_shares, num_shares), |b| { - b.iter(|| combine_fn()) - }); - } -} - -criterion_group!(benches, bench_encrypt_combine); -criterion_main!(benches); diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index e85d37d3..f05272a1 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -1,3 +1,4 @@ +pub mod test; mod utils; extern crate group_threshold_cryptography as tpke; @@ -5,35 +6,13 @@ extern crate group_threshold_cryptography as tpke; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use serde::{Deserialize, Serialize}; use serde_with::serde_as; -use tpke::api::*; use utils::set_panic_hook; use wasm_bindgen::prelude::*; extern crate wee_alloc; #[wasm_bindgen] -#[derive(Clone, Debug)] -pub struct PrivateDecryptionContext(tpke::api::PrivateDecryptionContext); - -#[wasm_bindgen] -impl PrivateDecryptionContext { - pub(crate) fn serialized_size() -> usize { - tpke::api::PrivateDecryptionContext::serialized_size() - } - - #[wasm_bindgen] - pub fn to_bytes(&self) -> Vec { - self.0.to_bytes() - } - - #[wasm_bindgen] - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(tpke::api::PrivateDecryptionContext::from_bytes(bytes)) - } -} - -#[wasm_bindgen] -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct DecryptionShare(tpke::api::DecryptionShare); #[wasm_bindgen] @@ -50,58 +29,12 @@ impl DecryptionShare { } } -#[wasm_bindgen] -#[derive(Clone, Debug)] -pub struct ParticipantPayload(tpke::api::ParticipantPayload); - -#[wasm_bindgen] -impl ParticipantPayload { - #[wasm_bindgen(constructor)] - pub fn new( - decryption_context: &PrivateDecryptionContext, - ciphertext: &Ciphertext, - ) -> Self { - Self(tpke::api::ParticipantPayload::new( - &decryption_context.0, - &ciphertext.ciphertext, - )) - } - - #[wasm_bindgen] - pub fn to_bytes(&self) -> Vec { - let mut bytes = self.0.decryption_context.to_bytes(); - bytes.extend(&self.0.ciphertext.to_bytes()); - bytes - } - - #[wasm_bindgen] - pub fn from_bytes(bytes: &[u8]) -> Self { - let decryption_context_bytes = - &bytes[0..PrivateDecryptionContext::serialized_size()]; - let decryption_context = - PrivateDecryptionContext::from_bytes(decryption_context_bytes); - - let ciphertext_bytes = - bytes[PrivateDecryptionContext::serialized_size()..].to_vec(); - let ciphertext = tpke::Ciphertext::from_bytes(&ciphertext_bytes); - - Self(tpke::api::ParticipantPayload { - decryption_context: decryption_context.0, - ciphertext, - }) - } - - #[wasm_bindgen] - pub fn to_decryption_share(&self) -> DecryptionShare { - DecryptionShare(self.0.to_decryption_share()) - } -} - #[serde_as] #[wasm_bindgen] #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct PublicKey( - #[serde_as(as = "tpke::serialization::SerdeAs")] pub(crate) TpkeDkgPublicKey, + #[serde_as(as = "tpke::serialization::SerdeAs")] + pub(crate) tpke::api::TpkeDkgPublicKey, ); #[wasm_bindgen] @@ -110,7 +43,8 @@ impl PublicKey { pub fn from_bytes(bytes: &[u8]) -> Self { let mut reader = bytes; let pk = - TpkeDkgPublicKey::deserialize_uncompressed(&mut reader).unwrap(); + tpke::api::TpkeDkgPublicKey::deserialize_uncompressed(&mut reader) + .unwrap(); PublicKey(pk) } @@ -126,7 +60,8 @@ impl PublicKey { #[wasm_bindgen] #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct PrivateKey( - #[serde_as(as = "tpke::serialization::SerdeAs")] pub(crate) TpkePrivateKey, + #[serde_as(as = "tpke::serialization::SerdeAs")] + pub(crate) tpke::api::TpkePrivateKey, ); #[wasm_bindgen] @@ -134,7 +69,9 @@ impl PrivateKey { #[wasm_bindgen] pub fn from_bytes(bytes: &[u8]) -> Self { let mut reader = bytes; - let pk = TpkePrivateKey::deserialize_uncompressed(&mut reader).unwrap(); + let pk = + tpke::api::TpkePrivateKey::deserialize_uncompressed(&mut reader) + .unwrap(); PrivateKey(pk) } @@ -147,74 +84,18 @@ impl PrivateKey { } #[wasm_bindgen] -#[derive(Clone, Debug)] -pub struct Setup { - pub public_key: PublicKey, - pub private_key: PrivateKey, - private_contexts: Vec, - public_contexts: Vec, -} +#[derive(Clone, Debug, PartialEq)] +pub struct Ciphertext(tpke::api::Ciphertext); #[wasm_bindgen] -impl Setup { - #[wasm_bindgen(constructor)] - pub fn new(threshold: usize, shares_num: usize) -> Self { - set_panic_hook(); - - let mut rng = rand::thread_rng(); - let (public_key, private_key, contexts) = - tpke::setup_fast::(threshold, shares_num, &mut rng); - let private_contexts = contexts - .clone() - .into_iter() - .map(|x| { - PrivateDecryptionContext( - tpke::api::PrivateDecryptionContext::new( - &x.setup_params.b_inv, - x.index, - ), - ) - }) - .collect(); - let public_contexts = contexts[0].public_decryption_contexts.to_vec(); - - Self { - public_key: PublicKey(public_key), - private_key: PrivateKey(private_key), - private_contexts, - public_contexts, - } - } - - // Using `private_context_at` and `decrypter_indexes` instead of making `private_context` public - // as a workaround for wasm-bindgen not supporting `Vec` with a custom defined types without serde - // serialization. - - #[wasm_bindgen] - pub fn private_context_at(&self, index: usize) -> PrivateDecryptionContext { - set_panic_hook(); - let context = self.private_contexts[index].clone(); - assert_eq!(context.0.decrypter_index, index); - context +impl Ciphertext { + pub fn from_bytes(bytes: &[u8]) -> Self { + Ciphertext(tpke::api::Ciphertext::from_bytes(bytes)) } - #[wasm_bindgen] - pub fn decrypter_indexes(&self) -> Vec { - set_panic_hook(); - self.private_contexts - .iter() - .map(|x| x.0.decrypter_index) - .collect() + pub fn to_bytes(&self) -> Vec { + self.0.to_bytes() } - - // TODO: Add `decryptorShares` helper method? -} - -#[wasm_bindgen] -#[derive(Clone, Debug)] -pub struct Ciphertext { - pub(crate) ciphertext: TpkeCiphertext, - pub(crate) aad: Vec, } #[wasm_bindgen] @@ -224,46 +105,38 @@ pub fn encrypt( public_key: &PublicKey, ) -> Ciphertext { set_panic_hook(); - let ciphertext = tpke::api::encrypt(message, aad, &public_key.0); - Ciphertext { - ciphertext, - aad: aad.to_vec(), - } + Ciphertext(tpke::api::encrypt(message, aad, &public_key.0)) } #[wasm_bindgen] pub fn decrypt_with_private_key( ciphertext: &Ciphertext, + aad: &[u8], private_key: &PrivateKey, ) -> Vec { set_panic_hook(); - tpke::decrypt_symmetric( - &ciphertext.ciphertext, - &ciphertext.aad, - private_key.0, - ) - .unwrap() + tpke::api::decrypt_symmetric(&ciphertext.0, aad, private_key.0) } #[wasm_bindgen] #[derive(Clone, Debug)] -pub struct SharedSecret(TpkeSharedSecret); +pub struct SharedSecret(tpke::api::TpkeSharedSecret); #[wasm_bindgen] #[derive(Clone, Debug)] pub struct SharedSecretBuilder { - shares: Vec, - contexts: Vec, + shares: Vec, + threshold: usize, } #[wasm_bindgen] impl SharedSecretBuilder { #[wasm_bindgen(constructor)] - pub fn new(setup: &Setup) -> Self { + pub fn new(threshold: usize) -> Self { SharedSecretBuilder { shares: vec![], - contexts: setup.public_contexts.clone(), + threshold, } } @@ -273,38 +146,25 @@ impl SharedSecretBuilder { } #[wasm_bindgen] - pub fn build(&self, ciphertext: &Ciphertext) -> SharedSecret { + pub fn build(&self) -> SharedSecret { set_panic_hook(); - if self.shares.len() != self.contexts.len() { - panic!("Number of shares and contexts must be equal"); + if self.shares.len() < self.threshold { + panic!("Number of shares below threshold"); } - let prepared_blinded_key_shares = - tpke::prepare_combine_fast(&self.contexts, &self.shares); - - let shared_secret = tpke::share_combine_fast( - &self.contexts, - &ciphertext.ciphertext, - &self.shares, - &prepared_blinded_key_shares, - ) - .unwrap(); - SharedSecret(shared_secret) + SharedSecret(tpke::share_combine_simple_precomputed(&self.shares)) } } #[wasm_bindgen] pub fn decrypt_with_shared_secret( ciphertext: &Ciphertext, + aad: &[u8], shared_secret: &SharedSecret, ) -> Vec { set_panic_hook(); - tpke::api::decrypt_with_shared_secret( - &ciphertext.ciphertext, - &ciphertext.aad, - &shared_secret.0, - ) - .unwrap() + tpke::api::decrypt_with_shared_secret(&ciphertext.0, aad, &shared_secret.0) + .unwrap() } diff --git a/tpke-wasm/src/test.rs b/tpke-wasm/src/test.rs new file mode 100644 index 00000000..f20a0351 --- /dev/null +++ b/tpke-wasm/src/test.rs @@ -0,0 +1,41 @@ +use crate::*; + +#[wasm_bindgen] +#[derive(Clone, Debug)] +pub struct Dkg { + pub public_key: PublicKey, + pub private_key: PrivateKey, + private_contexts: Vec, +} + +#[wasm_bindgen] +impl Dkg { + #[wasm_bindgen(constructor)] + pub fn new(threshold: usize, shares_num: usize) -> Self { + set_panic_hook(); + + let mut rng = rand::thread_rng(); + let (public_key, private_key, private_contexts) = + tpke::setup_simple::(threshold, shares_num, &mut rng); + Self { + public_key: PublicKey(public_key), + private_key: PrivateKey(private_key), + private_contexts, + } + } + + #[wasm_bindgen] + pub fn make_decryption_share( + &self, + ciphertext: &Ciphertext, + aad: &[u8], + validator_index: usize, + ) -> DecryptionShare { + set_panic_hook(); + DecryptionShare(tpke::api::DecryptionShare( + self.private_contexts[validator_index] + .create_share_precomputed(&ciphertext.0 .0, aad) + .unwrap(), + )) + } +} diff --git a/tpke-wasm/tests/node.rs b/tpke-wasm/tests/node.rs index d9e14972..23ac35f1 100644 --- a/tpke-wasm/tests/node.rs +++ b/tpke-wasm/tests/node.rs @@ -1,126 +1,93 @@ //! Test suite for the Nodejs. +extern crate group_threshold_cryptography as tpke; extern crate wasm_bindgen_test; +use tpke_wasm::test::*; use tpke_wasm::*; use wasm_bindgen_test::*; #[test] #[wasm_bindgen_test] -pub fn participant_payload_serialization() { - // Taking a shortcut here to generate a ciphertext - // TODO: Build a ciphertext from scratch - let threshold = 3; - let shares_num = 5; - let message = "my-secret-message".as_bytes().to_vec(); - let aad = "my-aad".as_bytes().to_vec(); - let setup = Setup::new(threshold, shares_num); - let ciphertext = encrypt(&message, &aad, &setup.public_key); - - let participant_payload = - ParticipantPayload::new(&setup.private_context_at(0), &ciphertext); - let serialized = participant_payload.to_bytes(); - let deserialized: ParticipantPayload = - ParticipantPayload::from_bytes(&serialized); - - assert_eq!(serialized, deserialized.to_bytes()) -} - -#[test] -#[wasm_bindgen_test] -fn encrypts_and_decrypts() { - let threshold = 3; - let shares_num = 5; - let message = "my-secret-message".as_bytes().to_vec(); - let aad = "my-aad".as_bytes().to_vec(); - - let setup = Setup::new(threshold, shares_num); - - let ciphertext = encrypt(&message, &aad, &setup.public_key); - let plaintext = decrypt_with_private_key(&ciphertext, &setup.private_key); - - // TODO: Plaintext is padded to 32 bytes. Fix this. - assert_eq!(message, plaintext[..message.len()]) -} - -#[test] -#[wasm_bindgen_test] -fn threshold_encryption() { - let threshold = 16 * 2 / 3; +fn tdec_simple_precomputed() { + // TODO: This test is not working. Fix it. + // It only works for these parameters: let shares_num = 16; + let threshold = 16; + // Uncomment to see the error: + // let shares_num = 16; + // let threshold = shares_num * 2 / 3; let message = "my-secret-message".as_bytes().to_vec(); let aad = "my-aad".as_bytes().to_vec(); + let dkg = Dkg::new(threshold, shares_num); + let dkg_pk = dkg.public_key; + // // On the client side // - // Initialize the DKG setup - let setup = Setup::new(threshold, shares_num); - // Encrypt the message - let ciphertext = encrypt(&message, &aad, &setup.public_key); - - // Craete and serialize participant payloads for transport - let participant_payloads_bytes: Vec> = setup - .decrypter_indexes() - .iter() - .map(|index| { - ParticipantPayload::new( - &setup.private_context_at(*index), - &ciphertext, - ) - .to_bytes() - }) - .collect(); - - // Now, deal the payloads to participants + let ciphertext = encrypt(&message, &aad, &dkg_pk); - // ================================================ + // Serialize and send to validators + let ciphertext_bytes = ciphertext.to_bytes(); // - // On the participants side + // On the server side // - // Deserialize from transport - let participant_payloads: Vec = - participant_payloads_bytes - .iter() - .map(|p| ParticipantPayload::from_bytes(p)) - .collect(); + let ciphertext2 = Ciphertext::from_bytes(&ciphertext_bytes); + assert_eq!(ciphertext, ciphertext2); // Create decryption shares - let decryption_shares: Vec = participant_payloads - .iter() - .map(|p| p.to_decryption_share()) - .collect(); - - // Serialize for transport - let decryption_shares_bytes: Vec> = - decryption_shares.iter().map(|s| s.to_bytes()).collect(); - - // Now, we send the shares back to the client + let decryption_shares = (0..threshold) + .map(|i| dkg.make_decryption_share(&ciphertext, &aad, i)) + .collect::>(); - // ================================================ + // Serialize and send back to client + let decryption_shares_bytes = decryption_shares + .iter() + .map(|s| s.to_bytes()) + .collect::>>(); // // On the client side // - // Deserialize from transport - let decryption_shares: Vec = decryption_shares_bytes + let decryption_shares_2: Vec = decryption_shares_bytes .iter() .map(|s| DecryptionShare::from_bytes(s)) .collect(); + assert_eq!(decryption_shares, decryption_shares_2); // Combine shares into a shared secret - let mut ss_builder = SharedSecretBuilder::new(&setup); + let mut ss_builder = SharedSecretBuilder::new(threshold); for share in decryption_shares { ss_builder.add_decryption_share(&share); } - let shared_secret = ss_builder.build(&ciphertext); + let shared_secret = ss_builder.build(); // Decrypt the message - let plaintext = decrypt_with_shared_secret(&ciphertext, &shared_secret); + let plaintext = + decrypt_with_shared_secret(&ciphertext, &aad, &shared_secret); assert_eq!(message, plaintext) } + +#[test] +#[wasm_bindgen_test] +fn encrypts_and_decrypts() { + let shares_num = 16; + let threshold = shares_num * 2 / 3; + let message = "my-secret-message".as_bytes().to_vec(); + let aad = "my-aad".as_bytes().to_vec(); + + let setup = Dkg::new(threshold, shares_num); + + let ciphertext = encrypt(&message, &aad, &setup.public_key); + let plaintext = + decrypt_with_private_key(&ciphertext, &aad, &setup.private_key); + + // TODO: Plaintext is padded to 32 bytes. Fix this. + assert_eq!(message, plaintext[..message.len()]) +} diff --git a/tpke/src/api.rs b/tpke/src/api.rs index 18fa4e09..9dfdc487 100644 --- a/tpke/src/api.rs +++ b/tpke/src/api.rs @@ -4,106 +4,46 @@ // TODO: Refactor this module to deduplicate shared code from tpke-wasm and tpke-wasm. -use ark_ec::{AffineCurve, ProjectiveCurve}; -use ark_ff::{BigInteger256, ToBytes}; -use std::convert::TryInto; - -// Fixing some of the types here on our target engine -// TODO: Consider fixing on crate::api level instead of bindings level pub type E = ark_bls12_381::Bls12_381; pub type TpkeDkgPublicKey = ark_bls12_381::G1Affine; pub type TpkePrivateKey = ark_bls12_381::G2Affine; pub type TpkeUnblindingKey = ark_bls12_381::Fr; pub type TpkeCiphertext = crate::Ciphertext; -pub type TpkeDecryptionShareFast = crate::DecryptionShareFast; -pub type TpkeDecryptionShareSimplePrecomputed = - crate::DecryptionShareSimplePrecomputed; -pub type TpkePublicDecryptionContext = crate::PublicDecryptionContextFast; -pub type TpkeSharedSecret = - ::Fqk; +pub type TpkeDecryptionShare = crate::DecryptionShareSimplePrecomputed; +pub type TpkePublicDecryptionContext = crate::PublicDecryptionContextSimple; +pub type TpkeSharedSecret = ::Fqk; pub type TpkeResult = crate::Result; +pub type TpkePrivateDecryptionContext = + crate::PrivateDecryptionContextSimple; pub fn encrypt( message: &[u8], aad: &[u8], pubkey: &TpkeDkgPublicKey, -) -> TpkeCiphertext { +) -> Ciphertext { // TODO: Should rng be a parameter? let rng = &mut rand::thread_rng(); - crate::encrypt(message, aad, pubkey, rng) + Ciphertext(crate::encrypt(message, aad, pubkey, rng)) } pub fn decrypt_with_shared_secret( - ciphertext: &TpkeCiphertext, + ciphertext: &Ciphertext, aad: &[u8], shared_secret: &TpkeSharedSecret, ) -> TpkeResult> { - crate::decrypt_with_shared_secret(ciphertext, aad, shared_secret) -} - -// TODO: There is previous API implementation below. I'm not removing it to avoid breaking bindings. -// Review it and decide if we need it. - -#[derive(Clone, Debug)] -pub struct PrivateDecryptionContext { - pub b_inv: ark_bls12_381::Fr, - pub decrypter_index: usize, + crate::decrypt_with_shared_secret(&ciphertext.0, aad, shared_secret) } -impl PrivateDecryptionContext { - const B_INV_LEN: usize = 32; - const DECRYPTER_INDEX_LEN: usize = 8; - - pub fn new(b_inv: &ark_bls12_381::Fr, decrypter_index: usize) -> Self { - Self { - b_inv: *b_inv, - decrypter_index, - } - } - - pub fn serialized_size() -> usize { - Self::B_INV_LEN + Self::DECRYPTER_INDEX_LEN - } - - pub fn to_bytes(&self) -> Vec { - let mut bytes = Vec::new(); - self.b_inv.0.write(&mut bytes).unwrap(); - - let decrypter_index = - bincode::serialize(&self.decrypter_index).unwrap(); - bytes.extend(decrypter_index); - - bytes - } - - pub fn from_bytes(bytes: &[u8]) -> Self { - let b_inv_bytes = &bytes[0..Self::B_INV_LEN]; - // Chunking bytes to u64s to construct a BigInteger256. - let b_inv = b_inv_bytes - .chunks(8) - .map(|x| { - let mut bytes = [0u8; 8]; - bytes.copy_from_slice(x); - u64::from_le_bytes(bytes) - }) - .collect::>(); - let b_inv: [u64; 4] = b_inv.try_into().unwrap(); - let b_inv = ark_bls12_381::Fr::new(BigInteger256::new(b_inv)); - - let decrypter_index_bytes = &bytes - [Self::B_INV_LEN..Self::B_INV_LEN + Self::DECRYPTER_INDEX_LEN]; - let decrypter_index = - bincode::deserialize(decrypter_index_bytes).unwrap(); - - Self { - b_inv, - decrypter_index, - } - } +pub fn decrypt_symmetric( + ciphertext: &Ciphertext, + aad: &[u8], + private_key: TpkePrivateKey, +) -> Vec { + crate::decrypt_symmetric(&ciphertext.0, aad, private_key).unwrap() } -#[derive(Clone, Debug)] -pub struct DecryptionShare(pub TpkeDecryptionShareFast); +#[derive(Clone, Debug, PartialEq)] +pub struct DecryptionShare(pub TpkeDecryptionShare); impl DecryptionShare { pub fn to_bytes(&self) -> Vec { @@ -111,64 +51,19 @@ impl DecryptionShare { } pub fn from_bytes(bytes: &[u8]) -> Self { - let share = TpkeDecryptionShareFast::from_bytes(bytes); - Self(share) + Self(TpkeDecryptionShare::from_bytes(bytes).unwrap()) } } -// TODO: Reconsider contents of ParticipantPayload payload after updating server API. - -#[derive(Clone, Debug)] -pub struct ParticipantPayload { - pub decryption_context: PrivateDecryptionContext, - pub ciphertext: TpkeCiphertext, -} - -impl ParticipantPayload { - pub fn new( - decryption_context: &PrivateDecryptionContext, - ciphertext: &TpkeCiphertext, - ) -> Self { - Self { - decryption_context: decryption_context.clone(), - ciphertext: ciphertext.clone(), - } - } - - pub fn to_bytes(&self) -> Vec { - let mut bytes = self.decryption_context.to_bytes(); - bytes.extend(&self.ciphertext.to_bytes()); - bytes - } +#[derive(Clone, Debug, PartialEq)] +pub struct Ciphertext(pub TpkeCiphertext); +impl Ciphertext { pub fn from_bytes(bytes: &[u8]) -> Self { - let decryption_context_bytes = - &bytes[0..PrivateDecryptionContext::serialized_size()]; - let decryption_context = - PrivateDecryptionContext::from_bytes(decryption_context_bytes); - - let ciphertext_bytes = - bytes[PrivateDecryptionContext::serialized_size()..].to_vec(); - let ciphertext: crate::Ciphertext = - crate::Ciphertext::from_bytes(&ciphertext_bytes); - - Self { - decryption_context, - ciphertext, - } + Ciphertext(TpkeCiphertext::from_bytes(bytes)) } - pub fn to_decryption_share(&self) -> DecryptionShare { - // TODO: Update how decryption share is constructed in this API - let decryption_share = self - .ciphertext - .commitment - .mul(self.decryption_context.b_inv) - .into_affine(); - - DecryptionShare(TpkeDecryptionShareFast { - decrypter_index: self.decryption_context.decrypter_index, - decryption_share, - }) + pub fn to_bytes(&self) -> Vec { + self.0.to_bytes() } } diff --git a/tpke/src/ciphertext.rs b/tpke/src/ciphertext.rs index ebe75cd1..1ce56923 100644 --- a/tpke/src/ciphertext.rs +++ b/tpke/src/ciphertext.rs @@ -9,7 +9,7 @@ use chacha20poly1305::{ }; use rand_core::RngCore; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct Ciphertext { pub commitment: E::G1Affine, // U pub auth_tag: E::G2Affine, // W @@ -34,10 +34,17 @@ impl Ciphertext { hash_to_g2(&hash_input) } + pub fn serialized_length(&self) -> usize { + self.commitment.serialized_size() + + self.auth_tag.serialized_size() + + self.ciphertext.len() + } + pub fn to_bytes(&self) -> Vec { let mut bytes = Vec::new(); self.commitment.write(&mut bytes).unwrap(); self.auth_tag.write(&mut bytes).unwrap(); + self.ciphertext.write(&mut bytes).unwrap(); bytes } @@ -142,12 +149,12 @@ pub fn decrypt_symmetric( fn decrypt_with_shared_secret_unchecked( ciphertext: &Ciphertext, - s: &E::Fqk, + shared_secret: &E::Fqk, ) -> Vec { let nonce = nonce_from_commitment::(ciphertext.commitment); let ciphertext = ciphertext.ciphertext.to_vec(); - let cipher = shared_secret_to_chacha::(s); + let cipher = shared_secret_to_chacha::(shared_secret); let plaintext = cipher.decrypt(&nonce, ciphertext.as_ref()).unwrap(); plaintext @@ -230,12 +237,12 @@ mod tests { let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); let pubkey = G1Projective::rand(rng).into_affine(); - let ciphertext = encrypt::(msg, aad, &pubkey, rng); - let serialized = ciphertext.to_bytes(); - let deserialized: Ciphertext = Ciphertext::from_bytes(&serialized); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let deserialized: Ciphertext = + Ciphertext::from_bytes(&ciphertext.to_bytes()); - assert_eq!(serialized, deserialized.to_bytes()) + assert_eq!(ciphertext, deserialized) } #[test] diff --git a/tpke/src/decryption.rs b/tpke/src/decryption.rs index f401316f..59741a8a 100644 --- a/tpke/src/decryption.rs +++ b/tpke/src/decryption.rs @@ -1,5 +1,6 @@ use crate::*; use ark_ec::ProjectiveCurve; +use ark_ff::FromBytes; use itertools::zip_eq; @@ -38,7 +39,6 @@ impl DecryptionShareFast { #[derive(Debug, Clone, PartialEq)] pub struct ValidatorShareChecksum { - // TODO: Consider replacing named inner variable with () syntax pub checksum: E::G1Affine, } @@ -77,6 +77,17 @@ impl ValidatorShareChecksum { true } + + pub fn from_bytes(bytes: &[u8]) -> Self { + let checksum = CanonicalDeserialize::deserialize(bytes).unwrap(); + Self { checksum } + } + + pub fn to_bytes(&self) -> Vec { + let mut bytes = Vec::new(); + CanonicalSerialize::serialize(&self.checksum, &mut bytes).unwrap(); + bytes + } } #[derive(Debug, Clone)] @@ -217,6 +228,46 @@ impl DecryptionShareSimplePrecomputed { ciphertext, ) } + + pub fn from_bytes(bytes: &[u8]) -> Result { + // TODO: usize type has different type in WASM (32 vs 64 bits) + let mut decrypter_index_bytes = [0u8; 8]; + let decrypter_index_len = decrypter_index_bytes.len(); + decrypter_index_bytes.copy_from_slice(&bytes[..decrypter_index_len]); + let decrypter_index = usize::from_be_bytes(decrypter_index_bytes); + + const DECRYPTION_SHARE_LEN: usize = 576; + let mut decryption_share_bytes = [0u8; DECRYPTION_SHARE_LEN]; + decryption_share_bytes.copy_from_slice( + &bytes[decrypter_index_len + ..decrypter_index_len + DECRYPTION_SHARE_LEN], + ); + let decryption_share = + E::Fqk::read(&decryption_share_bytes[..]).unwrap(); + + let validator_checksum_bytes = + &bytes[decrypter_index_len + DECRYPTION_SHARE_LEN..]; + let validator_checksum = + ValidatorShareChecksum::from_bytes(validator_checksum_bytes); + + Ok(Self { + decrypter_index, + decryption_share, + validator_checksum, + }) + } + + pub fn to_bytes(&self) -> Vec { + let mut bytes = Vec::new(); + bytes.extend_from_slice(&self.decrypter_index.to_be_bytes()); + let mut decryption_share_bytes = vec![]; + self.decryption_share + .serialize(&mut decryption_share_bytes) + .unwrap(); + bytes.extend_from_slice(&decryption_share_bytes); + bytes.extend_from_slice(&self.validator_checksum.to_bytes()); + bytes + } } // TODO: Remove this code? Currently only used in benchmarks. Move to benchmark suite? From d287129e0a687edc7dc40ce196461be6617dcbba Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Thu, 9 Feb 2023 12:48:21 +0100 Subject: [PATCH 15/36] refactor module visibility --- .github/workflows/workspace.yml | 4 + Cargo.lock | 415 +------------------------------- ferveo/Cargo.toml | 12 +- tpke-wasm/Cargo.toml | 13 +- tpke-wasm/src/lib.rs | 54 ++++- tpke-wasm/src/serialization.rs | 86 ------- tpke-wasm/src/test.rs | 41 ---- tpke-wasm/tests/node.rs | 3 +- tpke/Cargo.toml | 4 + tpke/benches/tpke.rs | 1 + tpke/src/README.md | 0 tpke/src/ciphertext.rs | 7 +- tpke/src/decryption.rs | 18 +- tpke/src/lib.rs | 404 ++++++++++++++++--------------- 14 files changed, 301 insertions(+), 761 deletions(-) delete mode 100644 tpke-wasm/src/serialization.rs delete mode 100644 tpke-wasm/src/test.rs delete mode 100644 tpke/src/README.md diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index db9463b8..87729efa 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -43,6 +43,10 @@ jobs: with: command: fmt args: --all -- --check + - uses: aig787/cargo-udeps-action@v1 + with: + version: 'latest' + args: '--all-targets' test: runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index 2dbbc9c8..4650b943 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "aead" version = "0.5.1" @@ -84,18 +69,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ark-ed-on-bls12-381" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b7ada17db3854f5994e74e60b18e10e818594935ee7e1d329800c117b32970" -dependencies = [ - "ark-bls12-381", - "ark-ec", - "ark-ff", - "ark-std", -] - [[package]] name = "ark-ff" version = "0.3.0" @@ -187,15 +160,6 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -dependencies = [ - "nodrop", -] - [[package]] name = "arrayvec" version = "0.7.2" @@ -219,21 +183,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "backtrace" -version = "0.3.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" -dependencies = [ - "addr2line", - "cc", - "cfg-if 1.0.0", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "base64" version = "0.13.1" @@ -255,15 +204,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "blake2" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388" -dependencies = [ - "digest 0.10.3", -] - [[package]] name = "blake2b_simd" version = "1.0.0" @@ -271,7 +211,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127" dependencies = [ "arrayref", - "arrayvec 0.7.2", + "arrayvec", "constant_time_eq", ] @@ -293,51 +233,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "borsh" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" -dependencies = [ - "borsh-derive", - "hashbrown 0.11.2", -] - -[[package]] -name = "borsh-derive" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate", - "proc-macro2", - "syn", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "bstr" version = "0.2.17" @@ -356,12 +251,6 @@ version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" -[[package]] -name = "bytemuck" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835" - [[package]] name = "byteorder" version = "1.4.3" @@ -531,15 +420,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" -[[package]] -name = "cpp_demangle" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" -dependencies = [ - "cfg-if 1.0.0", -] - [[package]] name = "cpufeatures" version = "0.2.2" @@ -791,15 +671,6 @@ dependencies = [ "syn", ] -[[package]] -name = "debugid" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ee87af31d84ef885378aebca32be3d682b0e0dc119d5b4860a2c5bb5046730" -dependencies = [ - "uuid", -] - [[package]] name = "derivative" version = "2.2.0" @@ -839,7 +710,6 @@ checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ "block-buffer 0.10.2", "crypto-common", - "subtle", ] [[package]] @@ -874,15 +744,6 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" -[[package]] -name = "fastrand" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" -dependencies = [ - "instant", -] - [[package]] name = "ferveo" version = "0.1.1" @@ -890,32 +751,25 @@ dependencies = [ "anyhow", "ark-bls12-381", "ark-ec", - "ark-ed-on-bls12-381", "ark-ff", "ark-poly", "ark-serialize", "ark-std", "bincode", - "blake2", "blake2b_simd", - "borsh", "criterion 0.3.6", "digest 0.10.3", "ed25519-dalek", "either", "ferveo-common", "group-threshold-cryptography", - "hex", "itertools", "measure_time", "miracl_core", - "num", - "pprof", "rand 0.7.3", "rand 0.8.5", "serde", "serde_bytes", - "serde_json", "subproductdomain", "subtle", "zeroize", @@ -948,18 +802,6 @@ dependencies = [ "rand 0.8.5", ] -[[package]] -name = "findshlibs" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" -dependencies = [ - "cc", - "lazy_static", - "libc", - "winapi", -] - [[package]] name = "fnv" version = "1.0.7" @@ -1000,12 +842,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "gimli" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" - [[package]] name = "group-threshold-cryptography" version = "0.1.0" @@ -1116,24 +952,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adab1eaa3408fb7f0c777a73e7465fd5656136fc93b670eb6df3c88c2c1344e3" -[[package]] -name = "inferno" -version = "0.10.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3886428c6400486522cf44b8626e7b94ad794c14390290f2a274dcf728a58f" -dependencies = [ - "ahash", - "atty", - "indexmap", - "itoa 1.0.3", - "lazy_static", - "log", - "num-format", - "quick-xml", - "rgb", - "str_stack", -] - [[package]] name = "inout" version = "0.1.3" @@ -1247,15 +1065,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" -[[package]] -name = "memmap2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a79b39c93a7a5a27eeaf9a23b5ff43f1b9e0ad6b1cdd441140ae53c35613fc7" -dependencies = [ - "libc", -] - [[package]] name = "memoffset" version = "0.6.5" @@ -1283,54 +1092,12 @@ dependencies = [ "zeroize", ] -[[package]] -name = "miniz_oxide" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" -dependencies = [ - "adler", -] - [[package]] name = "miracl_core" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94c7128ba23c81f6471141b90f17654f89ef44a56e14b8a4dd0fddfccd655277" -[[package]] -name = "nix" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" -dependencies = [ - "bitflags", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset", -] - -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - -[[package]] -name = "num" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.4.3" @@ -1342,25 +1109,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-complex" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-format" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" -dependencies = [ - "arrayvec 0.4.12", - "itoa 0.4.8", -] - [[package]] name = "num-integer" version = "0.1.45" @@ -1371,29 +1119,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.15" @@ -1413,15 +1138,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.13.0" @@ -1525,43 +1241,12 @@ dependencies = [ "universal-hash", ] -[[package]] -name = "pprof" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55f35f865aa964be21fcde114cbd1cfbd9bf8a471460ed965b0f84f96c711401" -dependencies = [ - "backtrace", - "cfg-if 1.0.0", - "criterion 0.3.6", - "findshlibs", - "inferno", - "lazy_static", - "libc", - "log", - "nix", - "parking_lot", - "smallvec", - "symbolic-demangle", - "tempfile", - "thiserror", -] - [[package]] name = "ppv-lite86" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - [[package]] name = "proc-macro2" version = "1.0.43" @@ -1631,15 +1316,6 @@ dependencies = [ "syn", ] -[[package]] -name = "quick-xml" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b" -dependencies = [ - "memchr", -] - [[package]] name = "quote" version = "1.0.21" @@ -1774,30 +1450,6 @@ version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - -[[package]] -name = "rgb" -version = "0.8.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b221de559e4a29df3b957eec92bc0de6bc8eaf6ca9cfed43e5e1d67ff65a34" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - [[package]] name = "rustc_version" version = "0.3.3" @@ -1961,18 +1613,6 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "str_stack" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" - [[package]] name = "strsim" version = "0.10.0" @@ -1998,29 +1638,6 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" -[[package]] -name = "symbolic-common" -version = "8.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f551f902d5642e58039aee6a9021a61037926af96e071816361644983966f540" -dependencies = [ - "debugid", - "memmap2", - "stable_deref_trait", - "uuid", -] - -[[package]] -name = "symbolic-demangle" -version = "8.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4564ca7b4e6eb14105aa8bbbce26e080f6b5d9c4373e67167ab31f7b86443750" -dependencies = [ - "cpp_demangle", - "rustc-demangle", - "symbolic-common", -] - [[package]] name = "syn" version = "1.0.99" @@ -2050,20 +1667,6 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" -[[package]] -name = "tempfile" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" -dependencies = [ - "cfg-if 1.0.0", - "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", -] - [[package]] name = "termcolor" version = "1.1.3" @@ -2145,15 +1748,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "toml" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" -dependencies = [ - "serde", -] - [[package]] name = "tpke-python" version = "0.1.0" @@ -2176,7 +1770,6 @@ dependencies = [ "console_error_panic_hook", "getrandom 0.2.7", "group-threshold-cryptography", - "js-sys", "rand 0.8.5", "rand_core 0.6.3", "serde", @@ -2232,12 +1825,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "uuid" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" - [[package]] name = "version_check" version = "0.9.4" diff --git a/ferveo/Cargo.toml b/ferveo/Cargo.toml index b0b0b4a9..53a2fd4f 100644 --- a/ferveo/Cargo.toml +++ b/ferveo/Cargo.toml @@ -20,34 +20,24 @@ ark-poly = "0.3" rand = "0.8" rand_old = { package = "rand", version = "0.7" } # used by benchmarks/pairing.rs either = "1.6.1" -hex = "0.4.2" miracl_core = "2.3.0" -num = "0.4" ed25519-dalek = { version = "1", features = ["serde", "batch"] } serde = { version = "1.0", features = ["derive"] } -blake2 = "0.10" blake2b_simd = "1" zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] } serde_bytes = { version = "0.11" } bincode = "1.3" anyhow = "1.0" -serde_json = "1.0" -borsh = "0.9" subtle = "2.4" itertools = "0.10.1" measure_time = "0.8" -ark-ed-on-bls12-381 = "0.3.0" group-threshold-cryptography = { path = "../tpke" } ferveo-common = { path = "../ferveo-common" } subproductdomain = { path = "../subproductdomain" } -[dependencies.digest] -version = "0.10.0" -features = ["alloc"] - [dev-dependencies] criterion = "0.3" # supports pprof, # TODO: Figure out if/how we can update to 0.4 -pprof = { version = "0.6", features = ["flamegraph", "criterion"] } +digest = { version = "0.10.0", features = ["alloc"] } [[example]] name = "pvdkg" diff --git a/tpke-wasm/Cargo.toml b/tpke-wasm/Cargo.toml index 04ec5a3e..55575ad2 100644 --- a/tpke-wasm/Cargo.toml +++ b/tpke-wasm/Cargo.toml @@ -12,13 +12,18 @@ crate-type = ["cdylib", "rlib"] [features] default = ["console_error_panic_hook"] +test-common = ["group-threshold-cryptography/test-common"] + +[[test]] +name = "wasm-node" +path = "tests/node.rs" +required-features = ["test-common"] [dependencies] +group-threshold-cryptography = { path = "../tpke" } wasm-bindgen = { version = "0.2.74", features = ["serde-serialize"] } -js-sys = "0.3.51" console_error_panic_hook = { version = "0.1.7", optional = true } wee_alloc = { version = "0.4.5" } -group-threshold-cryptography = { path = "../tpke"} getrandom = { version = "0.2", features = ["js"] } rand = "0.8.5" ark-bls12-381 = "0.3.0" @@ -31,6 +36,10 @@ ark-ec = "0.3" ark-std = "0.3.0" [dev-dependencies] +group-threshold-cryptography = { path = "../tpke", features = ["test-common"] } wasm-bindgen-test = "0.3.13" console_error_panic_hook = "0.1.7" rand_core = "0.6" + +[package.metadata.cargo-udeps.ignore] +development = ["wasm-bindgen-test"] \ No newline at end of file diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index f05272a1..a5a83317 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -1,12 +1,12 @@ -pub mod test; +extern crate group_threshold_cryptography as tpke; + mod utils; -extern crate group_threshold_cryptography as tpke; +use utils::*; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use serde::{Deserialize, Serialize}; use serde_with::serde_as; -use utils::set_panic_hook; use wasm_bindgen::prelude::*; extern crate wee_alloc; @@ -168,3 +168,51 @@ pub fn decrypt_with_shared_secret( tpke::api::decrypt_with_shared_secret(&ciphertext.0, aad, &shared_secret.0) .unwrap() } + +/// Factory functions for testing +#[cfg(any(test, feature = "test-common"))] +pub mod test_common { + use super::*; + + #[wasm_bindgen] + #[derive(Clone, Debug)] + pub struct Dkg { + pub public_key: PublicKey, + pub private_key: PrivateKey, + private_contexts: Vec, + } + + #[wasm_bindgen] + impl Dkg { + #[wasm_bindgen(constructor)] + pub fn new(threshold: usize, shares_num: usize) -> Self { + set_panic_hook(); + + let mut rng = rand::thread_rng(); + let (public_key, private_key, private_contexts) = + tpke::test_common::setup_simple::( + threshold, shares_num, &mut rng, + ); + Self { + public_key: PublicKey(public_key), + private_key: PrivateKey(private_key), + private_contexts, + } + } + + #[wasm_bindgen] + pub fn make_decryption_share( + &self, + ciphertext: &Ciphertext, + aad: &[u8], + validator_index: usize, + ) -> DecryptionShare { + set_panic_hook(); + DecryptionShare(tpke::api::DecryptionShare( + self.private_contexts[validator_index] + .create_share_precomputed(&ciphertext.0 .0, aad) + .unwrap(), + )) + } + } +} diff --git a/tpke-wasm/src/serialization.rs b/tpke-wasm/src/serialization.rs deleted file mode 100644 index 4d31db92..00000000 --- a/tpke-wasm/src/serialization.rs +++ /dev/null @@ -1,86 +0,0 @@ -//! This adds a few utility functions for serializing and deserializing -//! [arkworks](http://arkworks.rs/) types that implement [CanonicalSerialize] and [CanonicalDeserialize]. -//! Adapted from [o1-labs/proof-systems](https://raw.githubusercontent.com/o1-labs/proof-systems/31c76ceae3122f0ce09cded8260960ed5cbbe3d8/utils/src/serialization.rs). - -use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; -use serde_with::Bytes; - -// -// Serialization with serde -// - -#[allow(dead_code)] -pub mod ser { - //! You can use this module for serialization and deserializing arkworks types with [serde]. - //! Simply use the following attribute on your field: - //! `#[serde(with = "serialization::ser") attribute"]` - - use super::*; - use serde_with::{DeserializeAs, SerializeAs}; - - /// You can use this to serialize an arkworks type with serde and the "serialize_with" attribute. - /// See - pub fn serialize( - val: impl CanonicalSerialize, - serializer: S, - ) -> Result - where - S: serde::Serializer, - { - let mut bytes = vec![]; - val.serialize(&mut bytes) - .map_err(serde::ser::Error::custom)?; - - Bytes::serialize_as(&bytes, serializer) - } - - /// You can use this to deserialize an arkworks type with serde and the "deserialize_with" attribute. - /// See - pub fn deserialize<'de, T, D>(deserializer: D) -> Result - where - T: CanonicalDeserialize, - D: serde::Deserializer<'de>, - { - let bytes: Vec = Bytes::deserialize_as(deserializer)?; - T::deserialize(&mut &bytes[..]).map_err(serde::de::Error::custom) - } -} - -// -// Serialization with [serde_with] -// - -/// You can use [SerdeAs] with [serde_with] in order to serialize and deserialize types that implement [CanonicalSerialize] and [CanonicalDeserialize], -/// or containers of types that implement these traits (Vec, arrays, etc.) -/// Simply add annotations like `#[serde_as(as = "serialization::SerdeAs")]` -/// See -pub struct SerdeAs; - -impl serde_with::SerializeAs for SerdeAs -where - T: CanonicalSerialize, -{ - fn serialize_as(val: &T, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut bytes = vec![]; - val.serialize(&mut bytes) - .map_err(serde::ser::Error::custom)?; - - Bytes::serialize_as(&bytes, serializer) - } -} - -impl<'de, T> serde_with::DeserializeAs<'de, T> for SerdeAs -where - T: CanonicalDeserialize, -{ - fn deserialize_as(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let bytes: Vec = Bytes::deserialize_as(deserializer)?; - T::deserialize(&mut &bytes[..]).map_err(serde::de::Error::custom) - } -} diff --git a/tpke-wasm/src/test.rs b/tpke-wasm/src/test.rs deleted file mode 100644 index f20a0351..00000000 --- a/tpke-wasm/src/test.rs +++ /dev/null @@ -1,41 +0,0 @@ -use crate::*; - -#[wasm_bindgen] -#[derive(Clone, Debug)] -pub struct Dkg { - pub public_key: PublicKey, - pub private_key: PrivateKey, - private_contexts: Vec, -} - -#[wasm_bindgen] -impl Dkg { - #[wasm_bindgen(constructor)] - pub fn new(threshold: usize, shares_num: usize) -> Self { - set_panic_hook(); - - let mut rng = rand::thread_rng(); - let (public_key, private_key, private_contexts) = - tpke::setup_simple::(threshold, shares_num, &mut rng); - Self { - public_key: PublicKey(public_key), - private_key: PrivateKey(private_key), - private_contexts, - } - } - - #[wasm_bindgen] - pub fn make_decryption_share( - &self, - ciphertext: &Ciphertext, - aad: &[u8], - validator_index: usize, - ) -> DecryptionShare { - set_panic_hook(); - DecryptionShare(tpke::api::DecryptionShare( - self.private_contexts[validator_index] - .create_share_precomputed(&ciphertext.0 .0, aad) - .unwrap(), - )) - } -} diff --git a/tpke-wasm/tests/node.rs b/tpke-wasm/tests/node.rs index 23ac35f1..3aec03f8 100644 --- a/tpke-wasm/tests/node.rs +++ b/tpke-wasm/tests/node.rs @@ -3,8 +3,9 @@ extern crate group_threshold_cryptography as tpke; extern crate wasm_bindgen_test; -use tpke_wasm::test::*; +use tpke_wasm::test_common::*; use tpke_wasm::*; + use wasm_bindgen_test::*; #[test] diff --git a/tpke/Cargo.toml b/tpke/Cargo.toml index 3efd5d4b..869296af 100644 --- a/tpke/Cargo.toml +++ b/tpke/Cargo.toml @@ -11,6 +11,9 @@ readme = "README.md" [lib] bench = false +[features] +test-common = [] + [dependencies] hex = "=0.4.3" rand_core = "0.6" @@ -40,6 +43,7 @@ criterion = { version = "0.4", features = ["html_reports"] } name = "tpke" path = "benches/tpke.rs" harness = false +required-features = ["test-common"] # Hide this benchmark from boa-dev/criterion-compare-action@v3 #[[bench]] diff --git a/tpke/benches/tpke.rs b/tpke/benches/tpke.rs index 6ee0471b..e7d79f78 100644 --- a/tpke/benches/tpke.rs +++ b/tpke/benches/tpke.rs @@ -10,6 +10,7 @@ use criterion::{ }; use group_threshold_cryptography::*; +use group_threshold_cryptography::test_common::{setup_fast, setup_simple}; use rand::prelude::StdRng; use rand_core::{RngCore, SeedableRng}; diff --git a/tpke/src/README.md b/tpke/src/README.md deleted file mode 100644 index e69de29b..00000000 diff --git a/tpke/src/ciphertext.rs b/tpke/src/ciphertext.rs index 1ce56923..6c5a4d9a 100644 --- a/tpke/src/ciphertext.rs +++ b/tpke/src/ciphertext.rs @@ -219,10 +219,9 @@ fn construct_tag_hash( #[cfg(test)] mod tests { - use crate::{ - check_ciphertext_validity, decrypt_symmetric, encrypt, setup_fast, - Ciphertext, - }; + use crate::test_common::*; + use crate::*; + use ark_bls12_381::{Fr, G1Projective, G2Projective}; use ark_ec::ProjectiveCurve; use ark_ff::PrimeField; diff --git a/tpke/src/decryption.rs b/tpke/src/decryption.rs index 59741a8a..00590309 100644 --- a/tpke/src/decryption.rs +++ b/tpke/src/decryption.rs @@ -1,8 +1,10 @@ use crate::*; use ark_ec::ProjectiveCurve; use ark_ff::FromBytes; - +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use itertools::zip_eq; +use serde::{Deserialize, Serialize}; +use serde_with::serde_as; #[derive(Debug, Clone)] pub struct DecryptionShareFast { @@ -10,6 +12,13 @@ pub struct DecryptionShareFast { pub decryption_share: E::G1Affine, } +#[serde_as] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ValidatorShareChecksum { + #[serde_as(as = "serialization::SerdeAs")] + pub checksum: E::G1Affine, +} + impl DecryptionShareFast { pub fn to_bytes(&self) -> Vec { let mut bytes = Vec::new(); @@ -37,11 +46,6 @@ impl DecryptionShareFast { } } -#[derive(Debug, Clone, PartialEq)] -pub struct ValidatorShareChecksum { - pub checksum: E::G1Affine, -} - impl ValidatorShareChecksum { pub fn new( validator_decryption_key: &E::Fr, @@ -159,7 +163,7 @@ impl DecryptionShareSimple { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct DecryptionShareSimplePrecomputed { pub decrypter_index: usize, pub decryption_share: E::Fqk, diff --git a/tpke/src/lib.rs b/tpke/src/lib.rs index 35d69f67..cd02e6f1 100644 --- a/tpke/src/lib.rs +++ b/tpke/src/lib.rs @@ -1,30 +1,34 @@ -use crate::hash_to_curve::htp_bls12381_g2; -use crate::SetupParams; - use ark_ec::{AffineCurve, PairingEngine}; use ark_ff::{Field, One, PrimeField, UniformRand, Zero}; -use ark_poly::{ - univariate::DensePolynomial, EvaluationDomain, Polynomial, UVPolynomial, -}; -use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use ark_poly::{EvaluationDomain, UVPolynomial}; use itertools::izip; use rand_core::RngCore; use std::usize; -use subproductdomain::{fast_multiexp, SubproductDomain}; +use subproductdomain::SubproductDomain; use thiserror::Error; -mod ciphertext; -mod combine; -mod context; -mod decryption; -mod hash_to_curve; -mod key_share; -mod refresh; +pub mod ciphertext; +pub mod combine; +pub mod context; +pub mod decryption; +pub mod hash_to_curve; +pub mod key_share; +pub mod refresh; + +// TODO: Only show the public API, tpke::api +// use ciphertext::*; +// use combine::*; +// use context::*; +// use decryption::*; +// use hash_to_curve::*; +// use key_share::*; +// use refresh::*; pub use ciphertext::*; pub use combine::*; pub use context::*; pub use decryption::*; +pub use hash_to_curve::*; pub use key_share::*; pub use refresh::*; @@ -58,197 +62,213 @@ pub enum ThresholdEncryptionError { pub type Result = std::result::Result; -pub fn setup_fast( - threshold: usize, - shares_num: usize, - rng: &mut impl RngCore, -) -> ( - E::G1Affine, - E::G2Affine, - Vec>, -) { - assert!(shares_num >= threshold); - - // Generators G∈G1, H∈G2 - let g = E::G1Affine::prime_subgroup_generator(); - let h = E::G2Affine::prime_subgroup_generator(); - - // The dealer chooses a uniformly random polynomial f of degree t-1 - let threshold_poly = DensePolynomial::::rand(threshold - 1, rng); - // Domain, or omega Ω - let fft_domain = - ark_poly::Radix2EvaluationDomain::::new(shares_num).unwrap(); - // `evals` are evaluations of the polynomial f over the domain, omega: f(ω_j) for ω_j in Ω - let evals = threshold_poly.evaluate_over_domain_by_ref(fft_domain); - - // A - public key shares of participants - let pubkey_shares = fast_multiexp(&evals.evals, g.into_projective()); - let pubkey_share = g.mul(evals.evals[0]); - debug_assert!(pubkey_shares[0] == E::G1Affine::from(pubkey_share)); - - // Y, but only when b = 1 - private key shares of participants - let privkey_shares = fast_multiexp(&evals.evals, h.into_projective()); - - // a_0 - let x = threshold_poly.coeffs[0]; - - // F_0 - The commitment to the constant term, and is the public key output Y from PVDKG - let pubkey = g.mul(x); - let privkey = h.mul(x); - - let mut domain_points = Vec::with_capacity(shares_num); - let mut point = E::Fr::one(); - let mut domain_points_inv = Vec::with_capacity(shares_num); - let mut point_inv = E::Fr::one(); - - for _ in 0..shares_num { - domain_points.push(point); // 1, t, t^2, t^3, ...; where t is a scalar generator fft_domain.group_gen - point *= fft_domain.group_gen; - domain_points_inv.push(point_inv); - point_inv *= fft_domain.group_gen_inv; - } +/// Factory functions for testing +#[cfg(any(test, feature = "test-common"))] +pub mod test_common { + pub use super::*; + pub use ark_bls12_381::Bls12_381 as EllipticCurve; + pub use ark_ff::UniformRand; + use ark_poly::univariate::DensePolynomial; + use ark_poly::Polynomial; + use subproductdomain::fast_multiexp; + + pub fn setup_fast( + threshold: usize, + shares_num: usize, + rng: &mut impl RngCore, + ) -> ( + E::G1Affine, + E::G2Affine, + Vec>, + ) { + assert!(shares_num >= threshold); + + // Generators G∈G1, H∈G2 + let g = E::G1Affine::prime_subgroup_generator(); + let h = E::G2Affine::prime_subgroup_generator(); + + // The dealer chooses a uniformly random polynomial f of degree t-1 + let threshold_poly = DensePolynomial::::rand(threshold - 1, rng); + // Domain, or omega Ω + let fft_domain = + ark_poly::Radix2EvaluationDomain::::new(shares_num).unwrap(); + // `evals` are evaluations of the polynomial f over the domain, omega: f(ω_j) for ω_j in Ω + let evals = threshold_poly.evaluate_over_domain_by_ref(fft_domain); + + // A - public key shares of participants + let pubkey_shares = fast_multiexp(&evals.evals, g.into_projective()); + let pubkey_share = g.mul(evals.evals[0]); + debug_assert!(pubkey_shares[0] == E::G1Affine::from(pubkey_share)); + + // Y, but only when b = 1 - private key shares of participants + let privkey_shares = fast_multiexp(&evals.evals, h.into_projective()); + + // a_0 + let x = threshold_poly.coeffs[0]; + + // F_0 - The commitment to the constant term, and is the public key output Y from PVDKG + let pubkey = g.mul(x); + let privkey = h.mul(x); + + let mut domain_points = Vec::with_capacity(shares_num); + let mut point = E::Fr::one(); + let mut domain_points_inv = Vec::with_capacity(shares_num); + let mut point_inv = E::Fr::one(); + + for _ in 0..shares_num { + domain_points.push(point); // 1, t, t^2, t^3, ...; where t is a scalar generator fft_domain.group_gen + point *= fft_domain.group_gen; + domain_points_inv.push(point_inv); + point_inv *= fft_domain.group_gen_inv; + } + + let mut private_contexts = vec![]; + let mut public_contexts = vec![]; - let mut private_contexts = vec![]; - let mut public_contexts = vec![]; - - // (domain, domain_inv, A, Y) - for (index, (domain, domain_inv, public, private)) in izip!( - domain_points.iter(), - domain_points_inv.iter(), - pubkey_shares.iter(), - privkey_shares.iter() - ) - .enumerate() - { - let private_key_share = PrivateKeyShare:: { - private_key_share: *private, - }; - let b = E::Fr::rand(rng); - let mut blinded_key_shares = private_key_share.blind(b); - blinded_key_shares.multiply_by_omega_inv(domain_inv); - private_contexts.push(PrivateDecryptionContextFast:: { - index, - setup_params: SetupParams { - b, - b_inv: b.inverse().unwrap(), - g, + // (domain, domain_inv, A, Y) + for (index, (domain, domain_inv, public, private)) in izip!( + domain_points.iter(), + domain_points_inv.iter(), + pubkey_shares.iter(), + privkey_shares.iter() + ) + .enumerate() + { + let private_key_share = PrivateKeyShare:: { + private_key_share: *private, + }; + let b = E::Fr::rand(rng); + let mut blinded_key_shares = private_key_share.blind(b); + blinded_key_shares.multiply_by_omega_inv(domain_inv); + private_contexts.push(PrivateDecryptionContextFast:: { + index, + setup_params: SetupParams { + b, + b_inv: b.inverse().unwrap(), + g, + h_inv: E::G2Prepared::from(-h), + g_inv: E::G1Prepared::from(-g), + h, + }, + private_key_share, + public_decryption_contexts: vec![], + }); + public_contexts.push(PublicDecryptionContextFast:: { + domain: *domain, + public_key_share: PublicKeyShare:: { + public_key_share: *public, + }, + blinded_key_share: blinded_key_shares, + lagrange_n_0: *domain, h_inv: E::G2Prepared::from(-h), - g_inv: E::G1Prepared::from(-g), - h, - }, - private_key_share, - public_decryption_contexts: vec![], - }); - public_contexts.push(PublicDecryptionContextFast:: { - domain: *domain, - public_key_share: PublicKeyShare:: { - public_key_share: *public, - }, - blinded_key_share: blinded_key_shares, - lagrange_n_0: *domain, - h_inv: E::G2Prepared::from(-h), - }); - } - for private in private_contexts.iter_mut() { - private.public_decryption_contexts = public_contexts.clone(); - } + }); + } + for private in private_contexts.iter_mut() { + private.public_decryption_contexts = public_contexts.clone(); + } - (pubkey.into(), privkey.into(), private_contexts) -} + (pubkey.into(), privkey.into(), private_contexts) + } -pub fn setup_simple( - threshold: usize, - shares_num: usize, - rng: &mut impl RngCore, -) -> ( - E::G1Affine, - E::G2Affine, - Vec>, -) { - assert!(shares_num >= threshold); - - let g = E::G1Affine::prime_subgroup_generator(); - let h = E::G2Affine::prime_subgroup_generator(); - - // The dealer chooses a uniformly random polynomial f of degree t-1 - let threshold_poly = DensePolynomial::::rand(threshold - 1, rng); - // Domain, or omega Ω - let fft_domain = - ark_poly::Radix2EvaluationDomain::::new(shares_num).unwrap(); - // `evals` are evaluations of the polynomial f over the domain, omega: f(ω_j) for ω_j in Ω - let evals = threshold_poly.evaluate_over_domain_by_ref(fft_domain); - - let shares_x = fft_domain.elements().collect::>(); - - // A - public key shares of participants - let pubkey_shares = fast_multiexp(&evals.evals, g.into_projective()); - let pubkey_share = g.mul(evals.evals[0]); - assert!(pubkey_shares[0] == E::G1Affine::from(pubkey_share)); - - // Y, but only when b = 1 - private key shares of participants - let privkey_shares = fast_multiexp(&evals.evals, h.into_projective()); - - // a_0 - let x = threshold_poly.coeffs[0]; - // F_0 - let pubkey = g.mul(x); - let privkey = h.mul(x); - - let secret = threshold_poly.evaluate(&E::Fr::zero()); - assert_eq!(secret, x); - - let mut private_contexts = vec![]; - let mut public_contexts = vec![]; - - // (domain, A, Y) - for (index, (domain, public, private)) in - izip!(shares_x.iter(), pubkey_shares.iter(), privkey_shares.iter()) - .enumerate() - { - let private_key_share = PrivateKeyShare:: { - private_key_share: *private, - }; - let b = E::Fr::rand(rng); - let blinded_key_share = private_key_share.blind(b); - private_contexts.push(PrivateDecryptionContextSimple:: { - index, - setup_params: SetupParams { - b, - b_inv: b.inverse().unwrap(), - g, - h_inv: E::G2Prepared::from(-h), - g_inv: E::G1Prepared::from(-g), + pub fn setup_simple( + threshold: usize, + shares_num: usize, + rng: &mut impl RngCore, + ) -> ( + E::G1Affine, + E::G2Affine, + Vec>, + ) { + assert!(shares_num >= threshold); + + let g = E::G1Affine::prime_subgroup_generator(); + let h = E::G2Affine::prime_subgroup_generator(); + + // The dealer chooses a uniformly random polynomial f of degree t-1 + let threshold_poly = DensePolynomial::::rand(threshold - 1, rng); + // Domain, or omega Ω + let fft_domain = + ark_poly::Radix2EvaluationDomain::::new(shares_num).unwrap(); + // `evals` are evaluations of the polynomial f over the domain, omega: f(ω_j) for ω_j in Ω + let evals = threshold_poly.evaluate_over_domain_by_ref(fft_domain); + + let shares_x = fft_domain.elements().collect::>(); + + // A - public key shares of participants + let pubkey_shares = fast_multiexp(&evals.evals, g.into_projective()); + let pubkey_share = g.mul(evals.evals[0]); + assert!(pubkey_shares[0] == E::G1Affine::from(pubkey_share)); + + // Y, but only when b = 1 - private key shares of participants + let privkey_shares = fast_multiexp(&evals.evals, h.into_projective()); + + // a_0 + let x = threshold_poly.coeffs[0]; + // F_0 + let pubkey = g.mul(x); + let privkey = h.mul(x); + + let secret = threshold_poly.evaluate(&E::Fr::zero()); + assert_eq!(secret, x); + + let mut private_contexts = vec![]; + let mut public_contexts = vec![]; + + // (domain, A, Y) + for (index, (domain, public, private)) in + izip!(shares_x.iter(), pubkey_shares.iter(), privkey_shares.iter()) + .enumerate() + { + let private_key_share = PrivateKeyShare:: { + private_key_share: *private, + }; + let b = E::Fr::rand(rng); + let blinded_key_share = private_key_share.blind(b); + private_contexts.push(PrivateDecryptionContextSimple:: { + index, + setup_params: SetupParams { + b, + b_inv: b.inverse().unwrap(), + g, + h_inv: E::G2Prepared::from(-h), + g_inv: E::G1Prepared::from(-g), + h, + }, + private_key_share, + validator_private_key: b, + public_decryption_contexts: vec![], + }); + public_contexts.push(PublicDecryptionContextSimple:: { + domain: *domain, + public_key_share: PublicKeyShare:: { + public_key_share: *public, + }, + blinded_key_share, h, - }, - private_key_share, - validator_private_key: b, - public_decryption_contexts: vec![], - }); - public_contexts.push(PublicDecryptionContextSimple:: { - domain: *domain, - public_key_share: PublicKeyShare:: { - public_key_share: *public, - }, - blinded_key_share, - h, - validator_public_key: h.mul(b), - }); - } - for private in private_contexts.iter_mut() { - private.public_decryption_contexts = public_contexts.clone(); - } + validator_public_key: h.mul(b), + }); + } + for private in private_contexts.iter_mut() { + private.public_decryption_contexts = public_contexts.clone(); + } - (pubkey.into(), privkey.into(), private_contexts) + (pubkey.into(), privkey.into(), private_contexts) + } } #[cfg(test)] mod tests { - use crate::*; + use crate::test_common::*; + + use crate::refresh::{ + make_random_polynomial_at, prepare_share_updates_for_recovery, + recover_share_from_updated_private_shares, refresh_private_key_share, + update_share_for_recovery, + }; use ark_bls12_381::{Fr, FrParameters}; use ark_ec::ProjectiveCurve; use ark_ff::{BigInteger256, Fp256}; use ark_std::test_rng; - use rand::prelude::StdRng; use std::collections::HashMap; use std::ops::Mul; From 2e6b2317c44a0445db85fc9a1c58a71bb85e5c14 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Thu, 9 Feb 2023 18:07:39 +0100 Subject: [PATCH 16/36] update client api tests --- Cargo.lock | 1 + tpke-wasm/Cargo.toml | 11 ++---- tpke-wasm/src/lib.rs | 7 +--- tpke-wasm/tests/node.rs | 20 +++++----- tpke/Cargo.toml | 1 + tpke/src/api.rs | 4 +- tpke/src/ciphertext.rs | 56 +++++++++----------------- tpke/src/combine.rs | 2 +- tpke/src/decryption.rs | 88 ++++++++++------------------------------- tpke/src/lib.rs | 75 ++++++++++++++++++++++------------- 10 files changed, 106 insertions(+), 159 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4650b943..e14d31e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -857,6 +857,7 @@ dependencies = [ "blake2b_simd", "chacha20poly1305", "criterion 0.4.0", + "ferveo-common", "hex", "itertools", "miracl_core", diff --git a/tpke-wasm/Cargo.toml b/tpke-wasm/Cargo.toml index 55575ad2..5a211296 100644 --- a/tpke-wasm/Cargo.toml +++ b/tpke-wasm/Cargo.toml @@ -14,13 +14,8 @@ crate-type = ["cdylib", "rlib"] default = ["console_error_panic_hook"] test-common = ["group-threshold-cryptography/test-common"] -[[test]] -name = "wasm-node" -path = "tests/node.rs" -required-features = ["test-common"] - [dependencies] -group-threshold-cryptography = { path = "../tpke" } +group-threshold-cryptography = { path = "../tpke", features = ["test-common"] } wasm-bindgen = { version = "0.2.74", features = ["serde-serialize"] } console_error_panic_hook = { version = "0.1.7", optional = true } wee_alloc = { version = "0.4.5" } @@ -34,12 +29,12 @@ serde_with = "2.0.1" ark-serialize = { version = "0.3", features = ["derive"] } ark-ec = "0.3" ark-std = "0.3.0" +rand_core = "0.6" [dev-dependencies] -group-threshold-cryptography = { path = "../tpke", features = ["test-common"] } wasm-bindgen-test = "0.3.13" console_error_panic_hook = "0.1.7" rand_core = "0.6" [package.metadata.cargo-udeps.ignore] -development = ["wasm-bindgen-test"] \ No newline at end of file +development = ["wasm-bindgen-test"] diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index a5a83317..76232573 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -115,7 +115,6 @@ pub fn decrypt_with_private_key( private_key: &PrivateKey, ) -> Vec { set_panic_hook(); - tpke::api::decrypt_symmetric(&ciphertext.0, aad, private_key.0) } @@ -148,11 +147,9 @@ impl SharedSecretBuilder { #[wasm_bindgen] pub fn build(&self) -> SharedSecret { set_panic_hook(); - if self.shares.len() < self.threshold { panic!("Number of shares below threshold"); } - SharedSecret(tpke::share_combine_simple_precomputed(&self.shares)) } } @@ -164,13 +161,11 @@ pub fn decrypt_with_shared_secret( shared_secret: &SharedSecret, ) -> Vec { set_panic_hook(); - tpke::api::decrypt_with_shared_secret(&ciphertext.0, aad, &shared_secret.0) .unwrap() } /// Factory functions for testing -#[cfg(any(test, feature = "test-common"))] pub mod test_common { use super::*; @@ -184,10 +179,10 @@ pub mod test_common { #[wasm_bindgen] impl Dkg { + // TODO: Consider removing threshold from precomputed variant parameters #[wasm_bindgen(constructor)] pub fn new(threshold: usize, shares_num: usize) -> Self { set_panic_hook(); - let mut rng = rand::thread_rng(); let (public_key, private_key, private_contexts) = tpke::test_common::setup_simple::( diff --git a/tpke-wasm/tests/node.rs b/tpke-wasm/tests/node.rs index 3aec03f8..ee51ab6f 100644 --- a/tpke-wasm/tests/node.rs +++ b/tpke-wasm/tests/node.rs @@ -11,14 +11,9 @@ use wasm_bindgen_test::*; #[test] #[wasm_bindgen_test] fn tdec_simple_precomputed() { - // TODO: This test is not working. Fix it. - // It only works for these parameters: let shares_num = 16; - let threshold = 16; - // Uncomment to see the error: - // let shares_num = 16; - // let threshold = shares_num * 2 / 3; - let message = "my-secret-message".as_bytes().to_vec(); + let threshold = shares_num * 2 / 3; + let msg = "abc".as_bytes().to_vec(); let aad = "my-aad".as_bytes().to_vec(); let dkg = Dkg::new(threshold, shares_num); @@ -29,7 +24,7 @@ fn tdec_simple_precomputed() { // // Encrypt the message - let ciphertext = encrypt(&message, &aad, &dkg_pk); + let ciphertext = encrypt(&msg, &aad, &dkg_pk); // Serialize and send to validators let ciphertext_bytes = ciphertext.to_bytes(); @@ -42,7 +37,11 @@ fn tdec_simple_precomputed() { assert_eq!(ciphertext, ciphertext2); // Create decryption shares - let decryption_shares = (0..threshold) + + // Note that in this variant, if we use less than `share_num` shares, we will get a + // decryption error. + + let decryption_shares = (0..shares_num) .map(|i| dkg.make_decryption_share(&ciphertext, &aad, i)) .collect::>(); @@ -72,7 +71,8 @@ fn tdec_simple_precomputed() { // Decrypt the message let plaintext = decrypt_with_shared_secret(&ciphertext, &aad, &shared_secret); - assert_eq!(message, plaintext) + + assert_eq!(msg, plaintext) } #[test] diff --git a/tpke/Cargo.toml b/tpke/Cargo.toml index 869296af..d7249e2a 100644 --- a/tpke/Cargo.toml +++ b/tpke/Cargo.toml @@ -31,6 +31,7 @@ ark-std = "0.3" ark-bls12-381 = "0.3" itertools = "0.10" subproductdomain = { path = "../subproductdomain" } +ferveo-common = { path = "../ferveo-common" } chacha20poly1305 = "0.10.1" serde = { version = "1.0", features = ["derive"] } serde_with = "2.0.1" diff --git a/tpke/src/api.rs b/tpke/src/api.rs index 9dfdc487..063a21c7 100644 --- a/tpke/src/api.rs +++ b/tpke/src/api.rs @@ -19,11 +19,11 @@ pub type TpkePrivateDecryptionContext = pub fn encrypt( message: &[u8], aad: &[u8], - pubkey: &TpkeDkgPublicKey, + public_key: &TpkeDkgPublicKey, ) -> Ciphertext { // TODO: Should rng be a parameter? let rng = &mut rand::thread_rng(); - Ciphertext(crate::encrypt(message, aad, pubkey, rng)) + Ciphertext(crate::encrypt(message, aad, public_key, rng)) } pub fn decrypt_with_shared_secret( diff --git a/tpke/src/ciphertext.rs b/tpke/src/ciphertext.rs index 6c5a4d9a..cfeba4ea 100644 --- a/tpke/src/ciphertext.rs +++ b/tpke/src/ciphertext.rs @@ -1,19 +1,24 @@ use crate::*; use ark_ec::{AffineCurve, PairingEngine}; -use ark_ff::{FromBytes, One, ToBytes, UniformRand}; +use ark_ff::{One, ToBytes, UniformRand}; use ark_serialize::CanonicalSerialize; use chacha20poly1305::{ aead::{generic_array::GenericArray, Aead, KeyInit}, ChaCha20Poly1305, Nonce, }; use rand_core::RngCore; +use serde::{Deserialize, Serialize}; +use serde_with::serde_as; -#[derive(Clone, Debug, PartialEq)] +#[serde_as] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Ciphertext { + #[serde_as(as = "serialization::SerdeAs")] pub commitment: E::G1Affine, // U - pub auth_tag: E::G2Affine, // W - pub ciphertext: Vec, // V + #[serde_as(as = "serialization::SerdeAs")] + pub auth_tag: E::G2Affine, // W + pub ciphertext: Vec, // V } impl Ciphertext { @@ -41,33 +46,11 @@ impl Ciphertext { } pub fn to_bytes(&self) -> Vec { - let mut bytes = Vec::new(); - self.commitment.write(&mut bytes).unwrap(); - self.auth_tag.write(&mut bytes).unwrap(); - self.ciphertext.write(&mut bytes).unwrap(); - bytes + bincode::serialize(self).unwrap() } pub fn from_bytes(bytes: &[u8]) -> Self { - const COMMITMENT_LEN: usize = 97; - let mut commitment_bytes = [0u8; COMMITMENT_LEN]; - commitment_bytes.copy_from_slice(&bytes[..COMMITMENT_LEN]); - let commitment = E::G1Affine::read(&commitment_bytes[..]).unwrap(); - - const AUTH_TAG_LEN: usize = 193; - let mut auth_tag_bytes = [0u8; AUTH_TAG_LEN]; - auth_tag_bytes.copy_from_slice( - &bytes[COMMITMENT_LEN..COMMITMENT_LEN + AUTH_TAG_LEN], - ); - let auth_tag = E::G2Affine::read(&auth_tag_bytes[..]).unwrap(); - - let ciphertext = bytes[COMMITMENT_LEN + AUTH_TAG_LEN..].to_vec(); - - Self { - commitment, - ciphertext, - auth_tag, - } + bincode::deserialize(bytes).unwrap() } } @@ -130,7 +113,7 @@ pub fn check_ciphertext_validity( if is_ciphertext_valid { Ok(()) } else { - Err(ThresholdEncryptionError::CiphertextVerificationFailed) + Err(ThresholdEncryptionError::CiphertextVerificationFailed.into()) } } @@ -144,20 +127,22 @@ pub fn decrypt_symmetric( E::G1Prepared::from(ciphertext.commitment), E::G2Prepared::from(privkey), )]); - Ok(decrypt_with_shared_secret_unchecked(ciphertext, &s)) + decrypt_with_shared_secret_unchecked(ciphertext, &s) } fn decrypt_with_shared_secret_unchecked( ciphertext: &Ciphertext, shared_secret: &E::Fqk, -) -> Vec { +) -> Result> { let nonce = nonce_from_commitment::(ciphertext.commitment); let ciphertext = ciphertext.ciphertext.to_vec(); let cipher = shared_secret_to_chacha::(shared_secret); - let plaintext = cipher.decrypt(&nonce, ciphertext.as_ref()).unwrap(); + let plaintext = cipher + .decrypt(&nonce, ciphertext.as_ref()) + .map_err(|_| ThresholdEncryptionError::CiphertextVerificationFailed)?; - plaintext + Ok(plaintext) } pub fn decrypt_with_shared_secret( @@ -166,10 +151,7 @@ pub fn decrypt_with_shared_secret( shared_secret: &E::Fqk, ) -> Result> { check_ciphertext_validity(ciphertext, aad)?; - Ok(decrypt_with_shared_secret_unchecked( - ciphertext, - shared_secret, - )) + decrypt_with_shared_secret_unchecked(ciphertext, shared_secret) } fn blake2s_hash(input: &[u8]) -> Vec { diff --git a/tpke/src/combine.rs b/tpke/src/combine.rs index 0570d351..5a45c304 100644 --- a/tpke/src/combine.rs +++ b/tpke/src/combine.rs @@ -94,7 +94,7 @@ pub fn share_combine_fast( ); if !is_valid_shares { return Err( - ThresholdEncryptionError::DecryptionShareVerificationFailed, + ThresholdEncryptionError::DecryptionShareVerificationFailed.into(), ); } Ok(share_combine_fast_unchecked( diff --git a/tpke/src/decryption.rs b/tpke/src/decryption.rs index 00590309..ab47282b 100644 --- a/tpke/src/decryption.rs +++ b/tpke/src/decryption.rs @@ -1,51 +1,35 @@ use crate::*; use ark_ec::ProjectiveCurve; -use ark_ff::FromBytes; -use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; + +use anyhow::Result; use itertools::zip_eq; use serde::{Deserialize, Serialize}; use serde_with::serde_as; -#[derive(Debug, Clone)] +#[serde_as] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct DecryptionShareFast { pub decrypter_index: usize, - pub decryption_share: E::G1Affine, -} - -#[serde_as] -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct ValidatorShareChecksum { #[serde_as(as = "serialization::SerdeAs")] - pub checksum: E::G1Affine, + pub decryption_share: E::G1Affine, } impl DecryptionShareFast { pub fn to_bytes(&self) -> Vec { - let mut bytes = Vec::new(); - let decrypter_index = - bincode::serialize(&self.decrypter_index).unwrap(); - bytes.extend(&decrypter_index); - CanonicalSerialize::serialize(&self.decryption_share, &mut bytes) - .unwrap(); - - bytes + bincode::serialize(&self).unwrap() } pub fn from_bytes(bytes: &[u8]) -> Self { - let index_byte_len = 8; - let decrypter_index = - bincode::deserialize(&bytes[0..index_byte_len]).unwrap(); - let decryption_share = - CanonicalDeserialize::deserialize(&bytes[index_byte_len..]) - .unwrap(); - - DecryptionShareFast { - decrypter_index, - decryption_share, - } + bincode::deserialize(bytes).unwrap() } } +#[serde_as] +#[derive(CanonicalSerialize, CanonicalDeserialize, Debug, Clone, PartialEq)] +pub struct ValidatorShareChecksum { + pub checksum: E::G1Affine, +} + impl ValidatorShareChecksum { pub fn new( validator_decryption_key: &E::Fr, @@ -83,13 +67,12 @@ impl ValidatorShareChecksum { } pub fn from_bytes(bytes: &[u8]) -> Self { - let checksum = CanonicalDeserialize::deserialize(bytes).unwrap(); - Self { checksum } + CanonicalDeserialize::deserialize(bytes).unwrap() } pub fn to_bytes(&self) -> Vec { let mut bytes = Vec::new(); - CanonicalSerialize::serialize(&self.checksum, &mut bytes).unwrap(); + CanonicalSerialize::serialize(self, &mut bytes).unwrap(); bytes } } @@ -163,10 +146,13 @@ impl DecryptionShareSimple { } } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde_as] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DecryptionShareSimplePrecomputed { pub decrypter_index: usize, + #[serde_as(as = "serialization::SerdeAs")] pub decryption_share: E::Fqk, + #[serde(with = "ferveo_common::ark_serde")] pub validator_checksum: ValidatorShareChecksum, } @@ -234,43 +220,11 @@ impl DecryptionShareSimplePrecomputed { } pub fn from_bytes(bytes: &[u8]) -> Result { - // TODO: usize type has different type in WASM (32 vs 64 bits) - let mut decrypter_index_bytes = [0u8; 8]; - let decrypter_index_len = decrypter_index_bytes.len(); - decrypter_index_bytes.copy_from_slice(&bytes[..decrypter_index_len]); - let decrypter_index = usize::from_be_bytes(decrypter_index_bytes); - - const DECRYPTION_SHARE_LEN: usize = 576; - let mut decryption_share_bytes = [0u8; DECRYPTION_SHARE_LEN]; - decryption_share_bytes.copy_from_slice( - &bytes[decrypter_index_len - ..decrypter_index_len + DECRYPTION_SHARE_LEN], - ); - let decryption_share = - E::Fqk::read(&decryption_share_bytes[..]).unwrap(); - - let validator_checksum_bytes = - &bytes[decrypter_index_len + DECRYPTION_SHARE_LEN..]; - let validator_checksum = - ValidatorShareChecksum::from_bytes(validator_checksum_bytes); - - Ok(Self { - decrypter_index, - decryption_share, - validator_checksum, - }) + Ok(bincode::deserialize(bytes).unwrap()) } pub fn to_bytes(&self) -> Vec { - let mut bytes = Vec::new(); - bytes.extend_from_slice(&self.decrypter_index.to_be_bytes()); - let mut decryption_share_bytes = vec![]; - self.decryption_share - .serialize(&mut decryption_share_bytes) - .unwrap(); - bytes.extend_from_slice(&decryption_share_bytes); - bytes.extend_from_slice(&self.validator_checksum.to_bytes()); - bytes + bincode::serialize(self).unwrap() } } diff --git a/tpke/src/lib.rs b/tpke/src/lib.rs index cd02e6f1..249b0d2f 100644 --- a/tpke/src/lib.rs +++ b/tpke/src/lib.rs @@ -1,6 +1,7 @@ use ark_ec::{AffineCurve, PairingEngine}; use ark_ff::{Field, One, PrimeField, UniformRand, Zero}; use ark_poly::{EvaluationDomain, UVPolynomial}; +use ark_serialize::*; use itertools::izip; use rand_core::RngCore; use std::usize; @@ -42,12 +43,16 @@ pub trait ThresholdEncryptionParameters { #[derive(Debug, Error)] pub enum ThresholdEncryptionError { - /// Error + /// Ciphertext verification failed /// Refers to the check 4.4.2 in the paper: https://eprint.iacr.org/2022/898.pdf - #[error("ciphertext verification failed")] + #[error("Ciphertext verification failed")] CiphertextVerificationFailed, - /// Error + /// Symmetric ciphertext decryption failed + #[error("Ciphertext decryption failed")] + CiphertextDecryptionFailed, + + /// Decryption share verification failed /// Refers to the check 4.4.4 in the paper: https://eprint.iacr.org/2022/898.pdf #[error("Decryption share verification failed")] DecryptionShareVerificationFailed, @@ -56,11 +61,12 @@ pub enum ThresholdEncryptionError { #[error("Could not hash to curve")] HashToCurveError, - #[error("plaintext verification failed")] + #[error("Plaintext verification failed")] PlaintextVerificationFailed, } -pub type Result = std::result::Result; +// pub type Result = std::result::Result; +pub type Result = anyhow::Result; /// Factory functions for testing #[cfg(any(test, feature = "test-common"))] @@ -254,29 +260,8 @@ pub mod test_common { (pubkey.into(), privkey.into(), private_contexts) } -} - -#[cfg(test)] -mod tests { - use crate::test_common::*; - - use crate::refresh::{ - make_random_polynomial_at, prepare_share_updates_for_recovery, - recover_share_from_updated_private_shares, refresh_private_key_share, - update_share_for_recovery, - }; - use ark_bls12_381::{Fr, FrParameters}; - use ark_ec::ProjectiveCurve; - use ark_ff::{BigInteger256, Fp256}; - use ark_std::test_rng; - use rand::prelude::StdRng; - use std::collections::HashMap; - use std::ops::Mul; - - type E = ark_bls12_381::Bls12_381; - type Fqk = ::Fqk; - fn test_ciphertext_validation_fails( + pub fn test_ciphertext_validation_fails( msg: &[u8], aad: &[u8], ciphertext: &Ciphertext, @@ -298,6 +283,27 @@ mod tests { assert!(decrypt_with_shared_secret(&ciphertext, aad, shared_secret) .is_err()); } +} + +#[cfg(test)] +mod tests { + use crate::test_common::*; + + use crate::refresh::{ + make_random_polynomial_at, prepare_share_updates_for_recovery, + recover_share_from_updated_private_shares, refresh_private_key_share, + update_share_for_recovery, + }; + use ark_bls12_381::{Fr, FrParameters}; + use ark_ec::ProjectiveCurve; + use ark_ff::{BigInteger256, Fp256}; + use ark_std::test_rng; + use rand::prelude::StdRng; + use std::collections::HashMap; + use std::ops::Mul; + + type E = ark_bls12_381::Bls12_381; + type Fqk = ::Fqk; fn make_new_share_fragments( rng: &mut StdRng, @@ -472,8 +478,8 @@ mod tests { #[test] fn simple_threshold_decryption_precomputed() { let mut rng = &mut test_rng(); - let threshold = 16 * 2 / 3; let shares_num = 16; + let threshold = shares_num * 2 / 3; let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); @@ -493,6 +499,19 @@ mod tests { share_combine_simple_precomputed::(&decryption_shares); test_ciphertext_validation_fails(msg, aad, &ciphertext, &shared_secret); + + // Note that in this variant, if we use less than `share_num` shares, we will get a + // decryption error. + + let not_enough_shares = &decryption_shares[0..shares_num - 1]; + let bad_shared_secret = + share_combine_simple_precomputed::(not_enough_shares); + assert!(decrypt_with_shared_secret( + &ciphertext, + aad, + &bad_shared_secret, + ) + .is_err()); } #[test] From 6d92b010139b915da1a89ffa686bf24871c7afd1 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Fri, 10 Feb 2023 13:13:31 +0100 Subject: [PATCH 17/36] fix import style --- ferveo-common/src/lib.rs | 1 - ferveo/src/api.rs | 10 ++++++---- ferveo/src/dkg.rs | 1 - ferveo/src/dkg/common.rs | 16 +++++++++++++-- ferveo/src/dkg/pv.rs | 29 ++++++++++++++++++++------- ferveo/src/lib.rs | 37 +++++++++++++++++------------------ ferveo/src/msg.rs | 16 +++++++++++++-- ferveo/src/vss.rs | 15 +++++++++++++- ferveo/src/vss/pvss.rs | 23 +++++++++++++++++----- rustfmt.toml | 2 ++ subproductdomain/src/lib.rs | 3 ++- tpke-wasm/src/lib.rs | 3 +-- tpke-wasm/tests/node.rs | 1 - tpke/benches/arkworks.rs | 1 - tpke/benches/tpke.rs | 7 +++---- tpke/src/ciphertext.rs | 11 ++++++----- tpke/src/combine.rs | 12 ++++++++++-- tpke/src/context.rs | 9 +++++++-- tpke/src/decryption.rs | 19 ++++++++++++++---- tpke/src/key_share.rs | 6 ++++-- tpke/src/lib.rs | 39 +++++++++++++++++-------------------- tpke/src/refresh.rs | 5 +++-- tpke/src/serialization.rs | 3 ++- 23 files changed, 179 insertions(+), 90 deletions(-) diff --git a/ferveo-common/src/lib.rs b/ferveo-common/src/lib.rs index ab4c3329..b437bdf7 100644 --- a/ferveo-common/src/lib.rs +++ b/ferveo-common/src/lib.rs @@ -55,7 +55,6 @@ pub mod ark_serde { fn test_ark_serde() { use ark_bls12_381::G1Affine; use ark_ec::AffineCurve; - use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index cebc3e51..cae04561 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -212,8 +212,9 @@ impl AggregatedTranscript { #[cfg(test)] mod test_ferveo_api { - use crate::api::*; - use crate::dkg::test_common::*; + use std::collections::HashMap; + use std::fmt::format; + use ark_bls12_381::{Bls12_381 as E, Fr, G2Projective}; use ark_ec::ProjectiveCurve; use ark_poly::EvaluationDomain; @@ -224,8 +225,9 @@ mod test_ferveo_api { use itertools::{iproduct, izip}; use rand::prelude::StdRng; use rand::SeedableRng; - use std::collections::HashMap; - use std::fmt::format; + + use crate::api::*; + use crate::dkg::test_common::*; #[test] fn test_server_api_simple_tdec_precomputed() { diff --git a/ferveo/src/dkg.rs b/ferveo/src/dkg.rs index 7ccc9e82..d2963144 100644 --- a/ferveo/src/dkg.rs +++ b/ferveo/src/dkg.rs @@ -2,7 +2,6 @@ #![allow(non_snake_case)] #![allow(unused_imports)] -use crate::*; use anyhow::anyhow; use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; use ark_ff::Zero; diff --git a/ferveo/src/dkg/common.rs b/ferveo/src/dkg/common.rs index a96cebbb..d1edaa69 100644 --- a/ferveo/src/dkg/common.rs +++ b/ferveo/src/dkg/common.rs @@ -1,6 +1,18 @@ -use crate::*; +use std::collections::HashMap; + +use anyhow::{anyhow, Result}; +use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ff::{Field, One, PrimeField, Zero}; +use ark_poly::{ + polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, + EvaluationDomain, +}; +use ark_std::{end_timer, start_timer}; use ferveo_common::ExternalValidator; -use itertools::izip; +use ferveo_common::Rng; +use itertools::{izip, zip_eq}; +use measure_time::print_time; +use serde::{Deserialize, Serialize}; pub fn make_validators( validators: &[ExternalValidator], diff --git a/ferveo/src/dkg/pv.rs b/ferveo/src/dkg/pv.rs index 672cf30c..d771697f 100644 --- a/ferveo/src/dkg/pv.rs +++ b/ferveo/src/dkg/pv.rs @@ -1,13 +1,28 @@ -use crate::*; +use std::collections::BTreeMap; +use std::collections::HashMap; + use anyhow::Context; +use anyhow::{anyhow, Result}; use ark_ec::bn::TwistType::D; -use ark_ec::PairingEngine; -use ark_ff::Field; +use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ff::{Field, One, PrimeField, Zero}; +use ark_poly::{ + polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, + EvaluationDomain, +}; use ark_serialize::*; use ark_std::{end_timer, start_timer}; +use ferveo_common::Rng; use ferveo_common::{ExternalValidator, PublicKey}; +use itertools::{izip, zip_eq}; +use measure_time::print_time; use rand::RngCore; -use std::collections::BTreeMap; +use serde::{Deserialize, Serialize}; + +use crate::{ + aggregate, make_validators, AggregatedPvss, DkgState, Params, + PubliclyVerifiableParams, PubliclyVerifiableSS, Pvss, +}; /// The DKG context that holds all of the local state for participating in the DKG // TODO: Consider removing Clone to avoid accidentally NOT-mutating state. @@ -194,8 +209,7 @@ impl PubliclyVerifiableDkg { } = &mut self.state { *accumulated_shares += 1; - // TODO: Should be `== self.params.shares_num` instead? - if *accumulated_shares >= self.params.shares_num - self.params.security_threshold { + if *accumulated_shares >= self.params.security_threshold { self.state = DkgState::Dealt; } } @@ -258,10 +272,11 @@ pub enum Message { /// Factory functions for testing #[cfg(test)] pub(crate) mod test_common { - pub use super::*; pub use ark_bls12_381::Bls12_381 as EllipticCurve; pub use ark_ff::UniformRand; + pub use super::*; + pub type G1 = ::G1Affine; pub fn gen_n_keypairs( diff --git a/ferveo/src/lib.rs b/ferveo/src/lib.rs index 36ba9482..18916d88 100644 --- a/ferveo/src/lib.rs +++ b/ferveo/src/lib.rs @@ -1,21 +1,5 @@ #![allow(unused_imports)] -use anyhow::{anyhow, Result}; -use ark_ec::msm::FixedBaseMSM; -use ark_ec::PairingEngine; -use ark_ec::{AffineCurve, ProjectiveCurve}; -use ark_ff::PrimeField; -use ark_ff::{Field, One, Zero}; -use ark_poly::{ - polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, - EvaluationDomain, -}; -use ark_std::{end_timer, start_timer}; -use ferveo_common::Rng; -use itertools::{izip, zip_eq}; -use measure_time::print_time; -use serde::{Deserialize, Serialize}; - pub mod api; pub mod dkg; pub mod msg; @@ -29,25 +13,40 @@ pub use vss::*; #[cfg(test)] mod test_dkg_full { - use super::*; use std::collections::HashMap; - use crate::dkg::pv::test_common::*; + use anyhow::{anyhow, Result}; use ark_bls12_381::{ Bls12_381 as E, Bls12_381, Fr, G1Affine, G2Projective, }; use ark_ec::bls12::G2Affine; use ark_ec::group::Group; + use ark_ec::{ + msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve, + }; + use ark_ff::{Field, One, PrimeField, Zero}; use ark_ff::{Fp12, UniformRand}; + use ark_poly::{ + polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, + EvaluationDomain, + }; use ark_std::test_rng; + use ark_std::{end_timer, start_timer}; + use ferveo_common::Rng; use ferveo_common::{ExternalValidator, Keypair}; use group_threshold_cryptography as tpke; use group_threshold_cryptography::{ Ciphertext, DecryptionShareSimple, DecryptionShareSimplePrecomputed, }; - use itertools::{zip_eq, Itertools}; + use itertools::Itertools; + use itertools::{izip, zip_eq}; + use measure_time::print_time; use rand::prelude::StdRng; use rand::SeedableRng; + use serde::{Deserialize, Serialize}; + + use super::*; + use crate::dkg::pv::test_common::*; type Fqk = ::Fqk; diff --git a/ferveo/src/msg.rs b/ferveo/src/msg.rs index 8c53d387..841828a5 100644 --- a/ferveo/src/msg.rs +++ b/ferveo/src/msg.rs @@ -1,7 +1,19 @@ +use std::collections::HashMap; + +use anyhow::{anyhow, Result}; +use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ff::{Field, One, PrimeField, Zero}; +use ark_poly::{ + polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, + EvaluationDomain, +}; +use ark_std::{end_timer, start_timer}; use ed25519_dalek as ed25519; use ed25519_dalek::Signer; - -use crate::*; +use ferveo_common::Rng; +use itertools::{izip, zip_eq}; +use measure_time::print_time; +use serde::{Deserialize, Serialize}; impl SignedMessage { pub fn sign(tau: u64, msg: &M, key: &ed25519::Keypair) -> SignedMessage diff --git a/ferveo/src/vss.rs b/ferveo/src/vss.rs index da06c8c8..b864e0e8 100644 --- a/ferveo/src/vss.rs +++ b/ferveo/src/vss.rs @@ -1,7 +1,20 @@ pub mod pvss; -use crate::*; +use std::collections::HashMap; + +use anyhow::{anyhow, Result}; +use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ff::{Field, One, PrimeField, Zero}; +use ark_poly::{ + polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, + EvaluationDomain, +}; +use ark_std::{end_timer, start_timer}; +use ferveo_common::Rng; +use itertools::{izip, zip_eq}; +use measure_time::print_time; pub use pvss::*; +use serde::{Deserialize, Serialize}; /// The possible States of a VSS instance #[derive(Clone, Debug)] diff --git a/ferveo/src/vss/pvss.rs b/ferveo/src/vss/pvss.rs index 07f692cc..79549567 100644 --- a/ferveo/src/vss/pvss.rs +++ b/ferveo/src/vss/pvss.rs @@ -1,22 +1,35 @@ -use crate::*; use std::collections::BTreeMap; +use std::collections::HashMap; use std::marker::PhantomData; use std::ops::Add; +use anyhow::{anyhow, Result}; use ark_ec::bn::G2Affine; -use ark_ec::PairingEngine; +use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve}; use ark_ff::UniformRand; +use ark_ff::{Field, One, PrimeField, Zero}; +use ark_poly::{ + polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, + EvaluationDomain, +}; use ark_serialize::*; +use ark_std::{end_timer, start_timer}; +use ferveo_common::Rng; use ferveo_common::{Keypair, PublicKey}; use group_threshold_cryptography::{ prepare_combine_simple, refresh_private_key_share, update_share_for_recovery, Ciphertext, DecryptionShareFast, DecryptionShareSimple, DecryptionShareSimplePrecomputed, PrivateKeyShare, }; +use itertools::izip; use itertools::{zip_eq, Itertools}; +use measure_time::print_time; use rand::RngCore; +use serde::{Deserialize, Serialize}; use subproductdomain::fast_multiexp; +use crate::{batch_to_projective, PubliclyVerifiableDkg}; + /// These are the blinded evaluations of shares of a single random polynomial pub type ShareEncryptions = ::G2Affine; @@ -350,13 +363,13 @@ pub fn aggregate( #[cfg(test)] mod test_pvss { - use super::*; - - use crate::dkg::pv::test_common::*; use ark_bls12_381::Bls12_381 as EllipticCurve; use ark_ff::UniformRand; use ferveo_common::ExternalValidator; + use super::*; + use crate::dkg::pv::test_common::*; + type Fr = ::Fr; type G1 = ::G1Affine; type G2 = ::G2Affine; diff --git a/rustfmt.toml b/rustfmt.toml index d0ff29d2..de81e7e3 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -12,3 +12,5 @@ merge_derives = true use_try_shorthand = false use_field_init_shorthand = false force_explicit_abi = true +unstable_features = true +group_imports = "StdExternalCrate" \ No newline at end of file diff --git a/subproductdomain/src/lib.rs b/subproductdomain/src/lib.rs index e2d329ad..82977361 100644 --- a/subproductdomain/src/lib.rs +++ b/subproductdomain/src/lib.rs @@ -380,7 +380,6 @@ pub fn toeplitz_mul( #[cfg(test)] mod tests { - use super::*; use ark_ec::PairingEngine; use ark_ff::{One, Zero}; use ark_poly::polynomial::univariate::DensePolynomial; @@ -388,6 +387,8 @@ mod tests { use ark_poly::UVPolynomial; use ark_std::UniformRand; + use super::*; + type Fr = ::Fr; #[test] fn test_inverse() { diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index 76232573..b26a3f86 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -2,11 +2,10 @@ extern crate group_threshold_cryptography as tpke; mod utils; -use utils::*; - use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use serde::{Deserialize, Serialize}; use serde_with::serde_as; +use utils::*; use wasm_bindgen::prelude::*; extern crate wee_alloc; diff --git a/tpke-wasm/tests/node.rs b/tpke-wasm/tests/node.rs index ee51ab6f..2e41e97e 100644 --- a/tpke-wasm/tests/node.rs +++ b/tpke-wasm/tests/node.rs @@ -5,7 +5,6 @@ extern crate wasm_bindgen_test; use tpke_wasm::test_common::*; use tpke_wasm::*; - use wasm_bindgen_test::*; #[test] diff --git a/tpke/benches/arkworks.rs b/tpke/benches/arkworks.rs index 456efe55..a6afbbe4 100644 --- a/tpke/benches/arkworks.rs +++ b/tpke/benches/arkworks.rs @@ -7,7 +7,6 @@ use ark_ec::{ }; use ark_ff::{BigInteger256, Field, One, UniformRand, Zero}; use criterion::{black_box, criterion_group, BenchmarkId, Criterion}; - use group_threshold_cryptography::make_random_polynomial_at; use itertools::izip; use rand::prelude::StdRng; diff --git a/tpke/benches/tpke.rs b/tpke/benches/tpke.rs index e7d79f78..7a89f072 100644 --- a/tpke/benches/tpke.rs +++ b/tpke/benches/tpke.rs @@ -1,16 +1,15 @@ #![allow(clippy::redundant_closure)] +use std::collections::HashMap; + use ark_bls12_381::{Fr, G1Affine, G2Affine}; use ark_ec::AffineCurve; use ark_ff::Zero; -use std::collections::HashMap; - use criterion::{ black_box, criterion_group, criterion_main, BenchmarkId, Criterion, }; -use group_threshold_cryptography::*; - use group_threshold_cryptography::test_common::{setup_fast, setup_simple}; +use group_threshold_cryptography::*; use rand::prelude::StdRng; use rand_core::{RngCore, SeedableRng}; diff --git a/tpke/src/ciphertext.rs b/tpke/src/ciphertext.rs index cfeba4ea..f4e2a55a 100644 --- a/tpke/src/ciphertext.rs +++ b/tpke/src/ciphertext.rs @@ -1,5 +1,3 @@ -use crate::*; - use ark_ec::{AffineCurve, PairingEngine}; use ark_ff::{One, ToBytes, UniformRand}; use ark_serialize::CanonicalSerialize; @@ -11,6 +9,9 @@ use rand_core::RngCore; use serde::{Deserialize, Serialize}; use serde_with::serde_as; +use crate::serialization; +use crate::{htp_bls12381_g2, Result, ThresholdEncryptionError}; + #[serde_as] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Ciphertext { @@ -201,15 +202,15 @@ fn construct_tag_hash( #[cfg(test)] mod tests { - use crate::test_common::*; - use crate::*; - use ark_bls12_381::{Fr, G1Projective, G2Projective}; use ark_ec::ProjectiveCurve; use ark_ff::PrimeField; use ark_std::{test_rng, UniformRand}; use rand::prelude::StdRng; + use crate::test_common::*; + use crate::*; + type E = ark_bls12_381::Bls12_381; #[test] diff --git a/tpke/src/combine.rs b/tpke/src/combine.rs index 5a45c304..e0c05044 100644 --- a/tpke/src/combine.rs +++ b/tpke/src/combine.rs @@ -1,7 +1,15 @@ #![allow(non_snake_case)] -use crate::*; -use ark_ec::ProjectiveCurve; +use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ff::{Field, One, PrimeField, Zero}; +use itertools::izip; +use subproductdomain::SubproductDomain; + +use crate::{ + verify_decryption_shares_fast, Ciphertext, DecryptionShareFast, + DecryptionShareSimple, DecryptionShareSimplePrecomputed, + PublicDecryptionContextFast, Result, ThresholdEncryptionError, +}; pub fn prepare_combine_fast( public_decryption_contexts: &[PublicDecryptionContextFast], diff --git a/tpke/src/context.rs b/tpke/src/context.rs index 5b7a5e70..8c971740 100644 --- a/tpke/src/context.rs +++ b/tpke/src/context.rs @@ -1,5 +1,10 @@ -use crate::*; -use ark_ec::ProjectiveCurve; +use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; + +use crate::{ + check_ciphertext_validity, prepare_combine_simple, BlindedKeyShare, + Ciphertext, DecryptionShareFast, DecryptionShareSimple, + DecryptionShareSimplePrecomputed, PrivateKeyShare, PublicKeyShare, Result, +}; #[derive(Clone, Debug)] pub struct PublicDecryptionContextFast { diff --git a/tpke/src/decryption.rs b/tpke/src/decryption.rs index ab47282b..4c1cdbf6 100644 --- a/tpke/src/decryption.rs +++ b/tpke/src/decryption.rs @@ -1,11 +1,20 @@ -use crate::*; -use ark_ec::ProjectiveCurve; - use anyhow::Result; -use itertools::zip_eq; +use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ff::{Field, One, PrimeField, Zero}; +use ark_serialize::{ + CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write, +}; +use itertools::{izip, zip_eq}; +use rand_core::RngCore; use serde::{Deserialize, Serialize}; use serde_with::serde_as; +use crate::{ + check_ciphertext_validity, generate_random, serialization, Ciphertext, + PrivateKeyShare, PublicDecryptionContextFast, + PublicDecryptionContextSimple, +}; + #[serde_as] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DecryptionShareFast { @@ -354,6 +363,8 @@ pub fn verify_decryption_shares_simple( #[cfg(test)] mod tests { + use ark_ec::AffineCurve; + use crate::*; type E = ark_bls12_381::Bls12_381; diff --git a/tpke/src/key_share.rs b/tpke/src/key_share.rs index ae8ff8fd..c84dfc9e 100644 --- a/tpke/src/key_share.rs +++ b/tpke/src/key_share.rs @@ -1,5 +1,7 @@ -use crate::*; -use ark_ec::ProjectiveCurve; +use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ff::One; +use ark_std::UniformRand; +use rand_core::RngCore; #[derive(Debug, Clone)] pub struct PublicKeyShare { diff --git a/tpke/src/lib.rs b/tpke/src/lib.rs index 249b0d2f..9d5029de 100644 --- a/tpke/src/lib.rs +++ b/tpke/src/lib.rs @@ -1,11 +1,3 @@ -use ark_ec::{AffineCurve, PairingEngine}; -use ark_ff::{Field, One, PrimeField, UniformRand, Zero}; -use ark_poly::{EvaluationDomain, UVPolynomial}; -use ark_serialize::*; -use itertools::izip; -use rand_core::RngCore; -use std::usize; -use subproductdomain::SubproductDomain; use thiserror::Error; pub mod ciphertext; @@ -37,10 +29,6 @@ pub use refresh::*; pub mod api; pub mod serialization; -pub trait ThresholdEncryptionParameters { - type E: PairingEngine; -} - #[derive(Debug, Error)] pub enum ThresholdEncryptionError { /// Ciphertext verification failed @@ -71,13 +59,21 @@ pub type Result = anyhow::Result; /// Factory functions for testing #[cfg(any(test, feature = "test-common"))] pub mod test_common { - pub use super::*; + use std::usize; + pub use ark_bls12_381::Bls12_381 as EllipticCurve; + use ark_ec::{AffineCurve, PairingEngine}; pub use ark_ff::UniformRand; + use ark_ff::{Field, One, Zero}; use ark_poly::univariate::DensePolynomial; use ark_poly::Polynomial; + use ark_poly::{EvaluationDomain, UVPolynomial}; + use itertools::izip; + use rand_core::RngCore; use subproductdomain::fast_multiexp; + pub use super::*; + pub fn setup_fast( threshold: usize, shares_num: usize, @@ -287,20 +283,21 @@ pub mod test_common { #[cfg(test)] mod tests { - use crate::test_common::*; + use std::collections::HashMap; + use std::ops::Mul; + + use ark_bls12_381::{Fr, FrParameters}; + use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; + use ark_ff::{BigInteger256, Fp256, Zero}; + use ark_std::test_rng; + use rand::prelude::StdRng; use crate::refresh::{ make_random_polynomial_at, prepare_share_updates_for_recovery, recover_share_from_updated_private_shares, refresh_private_key_share, update_share_for_recovery, }; - use ark_bls12_381::{Fr, FrParameters}; - use ark_ec::ProjectiveCurve; - use ark_ff::{BigInteger256, Fp256}; - use ark_std::test_rng; - use rand::prelude::StdRng; - use std::collections::HashMap; - use std::ops::Mul; + use crate::test_common::*; type E = ark_bls12_381::Bls12_381; type Fqk = ::Fqk; diff --git a/tpke/src/refresh.rs b/tpke/src/refresh.rs index fffa88ad..f80b32f5 100644 --- a/tpke/src/refresh.rs +++ b/tpke/src/refresh.rs @@ -1,11 +1,12 @@ -use crate::{lagrange_basis_at, PrivateKeyShare}; +use std::usize; + use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; use ark_ff::{PrimeField, Zero}; use ark_poly::{univariate::DensePolynomial, Polynomial, UVPolynomial}; use itertools::zip_eq; use rand_core::RngCore; -use std::usize; +use crate::{lagrange_basis_at, PrivateKeyShare}; /// From PSS paper, section 4.2.1, (https://link.springer.com/content/pdf/10.1007/3-540-44750-4_27.pdf) pub fn prepare_share_updates_for_recovery( diff --git a/tpke/src/serialization.rs b/tpke/src/serialization.rs index 6117bd0c..f9496c92 100644 --- a/tpke/src/serialization.rs +++ b/tpke/src/serialization.rs @@ -14,9 +14,10 @@ pub mod ser { //! Simply use the following attribute on your field: //! `#[serde(with = "serialization::ser") attribute"]` - use super::*; use serde_with::{DeserializeAs, SerializeAs}; + use super::*; + /// You can use this to serialize an arkworks type with serde and the "serialize_with" attribute. /// See pub fn serialize( From 1cc35b480ebeb1f0ac6dcfd6c91e5ce627e9929c Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Fri, 10 Feb 2023 14:31:28 +0100 Subject: [PATCH 18/36] add simple tdec to wasm bindings --- ferveo/src/api.rs | 2 +- tpke-python/src/lib.rs | 2 +- tpke-wasm/src/lib.rs | 120 +++++++++++++++++++++++++++++++++++----- tpke-wasm/tests/node.rs | 87 ++++++++++++++++++++++++++--- tpke/src/api.rs | 46 +++++++++++++-- tpke/src/decryption.rs | 14 ++++- tpke/src/lib.rs | 4 +- 7 files changed, 245 insertions(+), 30 deletions(-) diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index cae04561..7b39405d 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -166,7 +166,7 @@ pub struct Ciphertext(pub tpke::api::Ciphertext); pub struct UnblindingKey(tpke::api::TpkeUnblindingKey); #[derive(Clone)] -pub struct DecryptionShare(tpke::api::TpkeDecryptionShare); +pub struct DecryptionShare(tpke::api::TpkeDecryptionShareSimplePrecomputed); pub struct AggregatedTranscript( crate::PubliclyVerifiableSS, diff --git a/tpke-python/src/lib.rs b/tpke-python/src/lib.rs index 130e7203..0cfef787 100644 --- a/tpke-python/src/lib.rs +++ b/tpke-python/src/lib.rs @@ -6,7 +6,7 @@ use pyo3::prelude::*; use pyo3::types::PyBytes; #[pyclass(module = "tpke")] -pub struct DecryptionShare(tpke::api::DecryptionShare); +pub struct DecryptionShare(tpke::api::DecryptionShareSimplePrecomputed); impl DecryptionShare { pub fn to_bytes(&self) -> PyResult { diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index b26a3f86..ba0ec47a 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -12,10 +12,10 @@ extern crate wee_alloc; #[wasm_bindgen] #[derive(Clone, Debug, PartialEq)] -pub struct DecryptionShare(tpke::api::DecryptionShare); +pub struct DecryptionShareSimple(tpke::api::DecryptionShareSimple); #[wasm_bindgen] -impl DecryptionShare { +impl DecryptionShareSimple { #[wasm_bindgen] pub fn to_bytes(&self) -> Vec { self.0.to_bytes() @@ -23,8 +23,28 @@ impl DecryptionShare { #[wasm_bindgen] pub fn from_bytes(bytes: &[u8]) -> Self { - let share = tpke::api::DecryptionShare::from_bytes(bytes); - Self(share) + Self(tpke::api::DecryptionShareSimple::from_bytes(bytes)) + } +} + +#[wasm_bindgen] +#[derive(Clone, Debug, PartialEq)] +pub struct DecryptionShareSimplePrecomputed( + tpke::api::DecryptionShareSimplePrecomputed, +); + +#[wasm_bindgen] +impl DecryptionShareSimplePrecomputed { + #[wasm_bindgen] + pub fn to_bytes(&self) -> Vec { + self.0.to_bytes() + } + + #[wasm_bindgen] + pub fn from_bytes(bytes: &[u8]) -> Self { + Self(tpke::api::DecryptionShareSimplePrecomputed::from_bytes( + bytes, + )) } } @@ -117,29 +137,36 @@ pub fn decrypt_with_private_key( tpke::api::decrypt_symmetric(&ciphertext.0, aad, private_key.0) } +#[wasm_bindgen] +#[derive(Clone, Debug)] +pub struct DomainPoint(tpke::api::DomainPoint); + #[wasm_bindgen] #[derive(Clone, Debug)] pub struct SharedSecret(tpke::api::TpkeSharedSecret); #[wasm_bindgen] #[derive(Clone, Debug)] -pub struct SharedSecretBuilder { - shares: Vec, +pub struct SharedSecretPrecomputedBuilder { + shares: Vec, threshold: usize, } #[wasm_bindgen] -impl SharedSecretBuilder { +impl SharedSecretPrecomputedBuilder { #[wasm_bindgen(constructor)] pub fn new(threshold: usize) -> Self { - SharedSecretBuilder { + Self { shares: vec![], threshold, } } #[wasm_bindgen] - pub fn add_decryption_share(&mut self, share: &DecryptionShare) { + pub fn add_decryption_share( + &mut self, + share: &DecryptionShareSimplePrecomputed, + ) { self.shares.push(share.0 .0.clone()); } @@ -153,6 +180,47 @@ impl SharedSecretBuilder { } } +#[wasm_bindgen] +#[derive(Clone, Debug)] +pub struct SharedSecretSimpleBuilder { + shares: Vec, + domain_points: Vec, + threshold: usize, +} + +#[wasm_bindgen] +impl SharedSecretSimpleBuilder { + #[wasm_bindgen(constructor)] + pub fn new(threshold: usize) -> Self { + Self { + shares: vec![], + domain_points: vec![], + threshold, + } + } + + #[wasm_bindgen] + pub fn add_decryption_share(&mut self, share: &DecryptionShareSimple) { + self.shares.push(share.0 .0.clone()); + } + + #[wasm_bindgen] + pub fn add_domain_point(&mut self, domain_point: &DomainPoint) { + self.domain_points.push(domain_point.0 .0); + } + + #[wasm_bindgen] + pub fn build(&self) -> SharedSecret { + set_panic_hook(); + if self.shares.len() < self.threshold { + panic!("Number of shares below threshold"); + } + let lagrange_coeffs = + tpke::prepare_combine_simple::(&self.domain_points); + SharedSecret(tpke::share_combine_simple(&self.shares, &lagrange_coeffs)) + } +} + #[wasm_bindgen] pub fn decrypt_with_shared_secret( ciphertext: &Ciphertext, @@ -195,18 +263,44 @@ pub mod test_common { } #[wasm_bindgen] - pub fn make_decryption_share( + pub fn make_decryption_share_simple( &self, ciphertext: &Ciphertext, aad: &[u8], validator_index: usize, - ) -> DecryptionShare { + ) -> DecryptionShareSimple { set_panic_hook(); - DecryptionShare(tpke::api::DecryptionShare( + DecryptionShareSimple(tpke::api::DecryptionShareSimple( self.private_contexts[validator_index] - .create_share_precomputed(&ciphertext.0 .0, aad) + .create_share(&ciphertext.0 .0, aad) .unwrap(), )) } + + #[wasm_bindgen] + pub fn make_decryption_share_precomputed( + &self, + ciphertext: &Ciphertext, + aad: &[u8], + validator_index: usize, + ) -> DecryptionShareSimplePrecomputed { + set_panic_hook(); + DecryptionShareSimplePrecomputed( + tpke::api::DecryptionShareSimplePrecomputed( + self.private_contexts[validator_index] + .create_share_precomputed(&ciphertext.0 .0, aad) + .unwrap(), + ), + ) + } + #[wasm_bindgen] + pub fn domain_point(&self, validator_index: usize) -> DomainPoint { + set_panic_hook(); + DomainPoint(tpke::api::DomainPoint( + self.private_contexts[0].public_decryption_contexts + [validator_index] + .domain, + )) + } } } diff --git a/tpke-wasm/tests/node.rs b/tpke-wasm/tests/node.rs index 2e41e97e..c83b4368 100644 --- a/tpke-wasm/tests/node.rs +++ b/tpke-wasm/tests/node.rs @@ -7,6 +7,78 @@ use tpke_wasm::test_common::*; use tpke_wasm::*; use wasm_bindgen_test::*; +#[test] +#[wasm_bindgen_test] +fn tdec_simple() { + let shares_num = 16; + let threshold = shares_num * 2 / 3; + let msg = "abc".as_bytes().to_vec(); + let aad = "my-aad".as_bytes().to_vec(); + + let dkg = Dkg::new(threshold, shares_num); + let dkg_pk = dkg.public_key; + + // + // On the client side + // + + // Encrypt the message + let ciphertext = encrypt(&msg, &aad, &dkg_pk); + + // Serialize and send to validators + let ciphertext_bytes = ciphertext.to_bytes(); + + // + // On the server side + // + + let ciphertext2 = Ciphertext::from_bytes(&ciphertext_bytes); + assert_eq!(ciphertext, ciphertext2); + + // Create decryption shares + + let decryption_shares = (0..threshold) + .map(|i| dkg.make_decryption_share_simple(&ciphertext, &aad, i)) + .collect::>(); + + let domain_points = (0..threshold) + .map(|i| dkg.domain_point(i)) + .collect::>(); + + // Serialize and send back to client + let decryption_shares_bytes = decryption_shares + .iter() + .map(|s| s.to_bytes()) + .collect::>>(); + + // + // On the client side + // + + let decryption_shares_2: Vec = + decryption_shares_bytes + .iter() + .map(|s| DecryptionShareSimple::from_bytes(s)) + .collect(); + assert_eq!(decryption_shares, decryption_shares_2); + + // Combine shares into a shared secret + let mut ss_builder = SharedSecretSimpleBuilder::new(threshold); + for share in decryption_shares { + ss_builder.add_decryption_share(&share); + } + for domain_point in domain_points { + ss_builder.add_domain_point(&domain_point); + } + let shared_secret = ss_builder.build(); + + // Decrypt the message + let plaintext = + decrypt_with_shared_secret(&ciphertext, &aad, &shared_secret); + + assert_eq!(msg, plaintext) +} + #[test] #[wasm_bindgen_test] fn tdec_simple_precomputed() { @@ -41,8 +113,8 @@ fn tdec_simple_precomputed() { // decryption error. let decryption_shares = (0..shares_num) - .map(|i| dkg.make_decryption_share(&ciphertext, &aad, i)) - .collect::>(); + .map(|i| dkg.make_decryption_share_precomputed(&ciphertext, &aad, i)) + .collect::>(); // Serialize and send back to client let decryption_shares_bytes = decryption_shares @@ -54,14 +126,15 @@ fn tdec_simple_precomputed() { // On the client side // - let decryption_shares_2: Vec = decryption_shares_bytes - .iter() - .map(|s| DecryptionShare::from_bytes(s)) - .collect(); + let decryption_shares_2: Vec = + decryption_shares_bytes + .iter() + .map(|s| DecryptionShareSimplePrecomputed::from_bytes(s)) + .collect(); assert_eq!(decryption_shares, decryption_shares_2); // Combine shares into a shared secret - let mut ss_builder = SharedSecretBuilder::new(threshold); + let mut ss_builder = SharedSecretPrecomputedBuilder::new(threshold); for share in decryption_shares { ss_builder.add_decryption_share(&share); } diff --git a/tpke/src/api.rs b/tpke/src/api.rs index 063a21c7..00fd3860 100644 --- a/tpke/src/api.rs +++ b/tpke/src/api.rs @@ -4,12 +4,17 @@ // TODO: Refactor this module to deduplicate shared code from tpke-wasm and tpke-wasm. +use ark_serialize::*; + pub type E = ark_bls12_381::Bls12_381; pub type TpkeDkgPublicKey = ark_bls12_381::G1Affine; pub type TpkePrivateKey = ark_bls12_381::G2Affine; pub type TpkeUnblindingKey = ark_bls12_381::Fr; +pub type TpkeDomainPoint = ark_bls12_381::Fr; pub type TpkeCiphertext = crate::Ciphertext; -pub type TpkeDecryptionShare = crate::DecryptionShareSimplePrecomputed; +pub type TpkeDecryptionShareSimplePrecomputed = + crate::DecryptionShareSimplePrecomputed; +pub type TpkeDecryptionShareSimple = crate::DecryptionShareSimple; pub type TpkePublicDecryptionContext = crate::PublicDecryptionContextSimple; pub type TpkeSharedSecret = ::Fqk; pub type TpkeResult = crate::Result; @@ -42,16 +47,49 @@ pub fn decrypt_symmetric( crate::decrypt_symmetric(&ciphertext.0, aad, private_key).unwrap() } +#[derive(Clone, Debug, PartialEq, CanonicalSerialize, CanonicalDeserialize)] +pub struct DomainPoint(pub TpkeDomainPoint); + +impl DomainPoint { + pub fn to_bytes(&self) -> Vec { + let mut bytes = vec![]; + CanonicalSerialize::serialize(&self.0, &mut bytes[..]).unwrap(); + bytes + } + + pub fn from_bytes(bytes: &[u8]) -> Self { + let mut reader = bytes; + let domain_point = + CanonicalDeserialize::deserialize(&mut reader).unwrap(); + Self(domain_point) + } +} + +#[derive(Clone, Debug, PartialEq)] +pub struct DecryptionShareSimple(pub TpkeDecryptionShareSimple); + +impl DecryptionShareSimple { + pub fn to_bytes(&self) -> Vec { + self.0.to_bytes() + } + + pub fn from_bytes(bytes: &[u8]) -> Self { + Self(TpkeDecryptionShareSimple::from_bytes(bytes)) + } +} + #[derive(Clone, Debug, PartialEq)] -pub struct DecryptionShare(pub TpkeDecryptionShare); +pub struct DecryptionShareSimplePrecomputed( + pub TpkeDecryptionShareSimplePrecomputed, +); -impl DecryptionShare { +impl DecryptionShareSimplePrecomputed { pub fn to_bytes(&self) -> Vec { self.0.to_bytes() } pub fn from_bytes(bytes: &[u8]) -> Self { - Self(TpkeDecryptionShare::from_bytes(bytes).unwrap()) + Self(TpkeDecryptionShareSimplePrecomputed::from_bytes(bytes).unwrap()) } } diff --git a/tpke/src/decryption.rs b/tpke/src/decryption.rs index 4c1cdbf6..6c247341 100644 --- a/tpke/src/decryption.rs +++ b/tpke/src/decryption.rs @@ -33,7 +33,6 @@ impl DecryptionShareFast { } } -#[serde_as] #[derive(CanonicalSerialize, CanonicalDeserialize, Debug, Clone, PartialEq)] pub struct ValidatorShareChecksum { pub checksum: E::G1Affine, @@ -86,11 +85,14 @@ impl ValidatorShareChecksum { } } -#[derive(Debug, Clone)] +#[serde_as] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DecryptionShareSimple { // TODO: Add decryptor public key? Replace decryptor_index with public key? pub decrypter_index: usize, + #[serde_as(as = "serialization::SerdeAs")] pub decryption_share: E::Fqk, + #[serde(with = "ferveo_common::ark_serde")] pub validator_checksum: ValidatorShareChecksum, } @@ -153,6 +155,14 @@ impl DecryptionShareSimple { ciphertext, ) } + + pub fn from_bytes(bytes: &[u8]) -> Self { + bincode::deserialize(bytes).unwrap() + } + + pub fn to_bytes(&self) -> Vec { + bincode::serialize(&self).unwrap() + } } #[serde_as] diff --git a/tpke/src/lib.rs b/tpke/src/lib.rs index 9d5029de..f2668e90 100644 --- a/tpke/src/lib.rs +++ b/tpke/src/lib.rs @@ -370,8 +370,8 @@ mod tests { decryption_shares: &[DecryptionShareSimple], ) -> E::Fqk { let domain = pub_contexts.iter().map(|c| c.domain).collect::>(); - let lagrange = prepare_combine_simple::(&domain); - share_combine_simple::(decryption_shares, &lagrange) + let lagrange_coeffs = prepare_combine_simple::(&domain); + share_combine_simple::(decryption_shares, &lagrange_coeffs) } #[test] From d588cc8d339f8f4fb336fa447dbd914faee80604 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Fri, 10 Feb 2023 17:02:36 +0100 Subject: [PATCH 19/36] update dev deps settings --- Cargo.lock | 277 ++++++++++++++++++++++++++++++++++++++- ferveo-python/Cargo.toml | 2 +- ferveo/Cargo.toml | 11 +- tpke/Cargo.toml | 4 +- tpke/src/lib.rs | 6 +- 5 files changed, 288 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89ef78b8..050ab068 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aead" version = "0.5.1" @@ -160,6 +175,15 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + [[package]] name = "arrayvec" version = "0.7.2" @@ -183,6 +207,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.13.1" @@ -211,7 +250,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127" dependencies = [ "arrayref", - "arrayvec", + "arrayvec 0.7.2", "constant_time_eq", ] @@ -251,6 +290,12 @@ version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +[[package]] +name = "bytemuck" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" + [[package]] name = "byteorder" version = "1.4.3" @@ -420,6 +465,15 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "cpp_demangle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "cpufeatures" version = "0.2.5" @@ -669,6 +723,15 @@ dependencies = [ "syn", ] +[[package]] +name = "debugid" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ee87af31d84ef885378aebca32be3d682b0e0dc119d5b4860a2c5bb5046730" +dependencies = [ + "uuid", +] + [[package]] name = "derivative" version = "2.2.0" @@ -742,6 +805,15 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + [[package]] name = "ferveo" version = "0.1.1" @@ -764,6 +836,7 @@ dependencies = [ "itertools", "measure_time", "miracl_core", + "pprof", "rand 0.7.3", "rand 0.8.5", "rand_core 0.6.4", @@ -801,6 +874,18 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "findshlibs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" +dependencies = [ + "cc", + "lazy_static", + "libc", + "winapi", +] + [[package]] name = "fnv" version = "1.0.7" @@ -853,6 +938,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gimli" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "221996f774192f0f718773def8201c4ae31f02616a54ccfc2d358bb0e5cefdec" + [[package]] name = "group-threshold-cryptography" version = "0.1.0" @@ -964,6 +1055,24 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adab1eaa3408fb7f0c777a73e7465fd5656136fc93b670eb6df3c88c2c1344e3" +[[package]] +name = "inferno" +version = "0.10.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3886428c6400486522cf44b8626e7b94ad794c14390290f2a274dcf728a58f" +dependencies = [ + "ahash", + "atty", + "indexmap", + "itoa 1.0.4", + "lazy_static", + "log", + "num-format", + "quick-xml", + "rgb", + "str_stack", +] + [[package]] name = "inout" version = "0.1.3" @@ -1080,6 +1189,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memmap2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.5" @@ -1116,12 +1234,40 @@ dependencies = [ "zeroize", ] +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + [[package]] name = "miracl_core" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94c7128ba23c81f6471141b90f17654f89ef44a56e14b8a4dd0fddfccd655277" +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags", + "cc", + "cfg-if 1.0.0", + "libc", + "memoffset 0.6.5", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + [[package]] name = "num-bigint" version = "0.4.3" @@ -1133,6 +1279,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-format" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" +dependencies = [ + "arrayvec 0.4.12", + "itoa 0.4.8", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -1162,6 +1318,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.16.0" @@ -1265,6 +1430,28 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "pprof" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55f35f865aa964be21fcde114cbd1cfbd9bf8a471460ed965b0f84f96c711401" +dependencies = [ + "backtrace", + "cfg-if 1.0.0", + "criterion 0.3.6", + "findshlibs", + "inferno", + "lazy_static", + "libc", + "log", + "nix", + "parking_lot", + "smallvec", + "symbolic-demangle", + "tempfile", + "thiserror", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1340,6 +1527,15 @@ dependencies = [ "syn", ] +[[package]] +name = "quick-xml" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "1.0.21" @@ -1520,6 +1716,24 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rgb" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7495acf66551cdb696b7711408144bcd3194fc78e32f3a09e809bfe7dd4a7ce3" +dependencies = [ + "bytemuck", +] + [[package]] name = "rust-crypto" version = "0.2.36" @@ -1533,6 +1747,12 @@ dependencies = [ "time 0.1.44", ] +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + [[package]] name = "rustc-serialize" version = "0.3.24" @@ -1702,6 +1922,18 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "str_stack" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" + [[package]] name = "strsim" version = "0.10.0" @@ -1727,6 +1959,29 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "symbolic-common" +version = "8.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f551f902d5642e58039aee6a9021a61037926af96e071816361644983966f540" +dependencies = [ + "debugid", + "memmap2", + "stable_deref_trait", + "uuid", +] + +[[package]] +name = "symbolic-demangle" +version = "8.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4564ca7b4e6eb14105aa8bbbce26e080f6b5d9c4373e67167ab31f7b86443750" +dependencies = [ + "cpp_demangle", + "rustc-demangle", + "symbolic-common", +] + [[package]] name = "syn" version = "1.0.103" @@ -1756,6 +2011,20 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if 1.0.0", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + [[package]] name = "termcolor" version = "1.1.3" @@ -1925,6 +2194,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" + [[package]] name = "version_check" version = "0.9.4" diff --git a/ferveo-python/Cargo.toml b/ferveo-python/Cargo.toml index 6b303b83..0087014f 100644 --- a/ferveo-python/Cargo.toml +++ b/ferveo-python/Cargo.toml @@ -8,8 +8,8 @@ edition = "2018" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.17.3", features = ["macros"] } ferveo = { path = "../ferveo" } +pyo3 = { version = "0.17.3", features = ["macros"] } group-threshold-cryptography = { path = "../tpke" } derive_more = { version = "0.99", default-features = false, features = ["from", "as_ref"] } rand = "0.8" diff --git a/ferveo/Cargo.toml b/ferveo/Cargo.toml index 05f6628a..8cb1ac7e 100644 --- a/ferveo/Cargo.toml +++ b/ferveo/Cargo.toml @@ -11,6 +11,9 @@ categories = ["cryptography"] authors = ["Heliax AG "] [dependencies] +group-threshold-cryptography = { path = "../tpke" } +ferveo-common = { path = "../ferveo-common" } +subproductdomain = { path = "../subproductdomain" } ark-std = "0.3" ark-bls12-381 = "0.3" ark-ec = "0.3" @@ -31,15 +34,16 @@ anyhow = "1.0" subtle = "2.4" itertools = "0.10.1" measure_time = "0.8" -group-threshold-cryptography = { path = "../tpke" } -ferveo-common = { path = "../ferveo-common" } -subproductdomain = { path = "../subproductdomain" } rand_core = "0.6.4" [dev-dependencies] criterion = "0.3" # supports pprof, # TODO: Figure out if/how we can update to 0.4 +pprof = { version = "0.6", features = ["flamegraph", "criterion"] } digest = { version = "0.10.0", features = ["alloc"] } +[package.metadata.cargo-udeps.ignore] +development = ["pprof"] + [[example]] name = "pvdkg" path = "examples/pvdkg.rs" @@ -54,7 +58,6 @@ name = "benchmarks" path = "benches/bench_main.rs" harness = false - [profile.release] opt-level = 3 lto = true diff --git a/tpke/Cargo.toml b/tpke/Cargo.toml index 48d8585b..92cd51f9 100644 --- a/tpke/Cargo.toml +++ b/tpke/Cargo.toml @@ -15,6 +15,8 @@ bench = false test-common = [] [dependencies] +subproductdomain = { path = "../subproductdomain" } +ferveo-common = { path = "../ferveo-common" } hex = "=0.4.3" rand_core = "0.6" rand = "0.8" @@ -30,8 +32,6 @@ ark-serialize = "0.3" ark-std = "0.3" ark-bls12-381 = "0.3" itertools = "0.10" -subproductdomain = { path = "../subproductdomain" } -ferveo-common = { path = "../ferveo-common" } chacha20poly1305 = "0.10.1" serde = { version = "1.0", features = ["derive"] } serde_with = "2.0.1" diff --git a/tpke/src/lib.rs b/tpke/src/lib.rs index 63725438..28023b86 100644 --- a/tpke/src/lib.rs +++ b/tpke/src/lib.rs @@ -1,5 +1,3 @@ -use thiserror::Error; - pub mod ciphertext; pub mod combine; pub mod context; @@ -29,7 +27,7 @@ pub use refresh::*; pub mod api; pub mod serialization; -#[derive(Debug, Error)] +#[derive(Debug, thiserror::Error)] pub enum ThresholdEncryptionError { /// Ciphertext verification failed /// Refers to the check 4.4.2 in the paper: https://eprint.iacr.org/2022/898.pdf @@ -49,11 +47,11 @@ pub enum ThresholdEncryptionError { #[error("Could not hash to curve")] HashToCurveError, + /// Plaintext verification failed #[error("Plaintext verification failed")] PlaintextVerificationFailed, } -// pub type Result = std::result::Result; pub type Result = anyhow::Result; /// Factory functions for testing From b1999b86a2b04c719ec29b1263612de88a0cfd49 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Tue, 14 Feb 2023 15:51:05 +0100 Subject: [PATCH 20/36] update arkworks to 0.4.0 - first pass --- Cargo.lock | 484 +++++++++++-------- ferveo-common/Cargo.toml | 13 +- ferveo-common/src/keypair.rs | 62 +-- ferveo-common/src/lib.rs | 65 +-- {tpke => ferveo-common}/src/serialization.rs | 10 +- ferveo/Cargo.lock | 20 +- ferveo/Cargo.toml | 13 +- ferveo/benches/benchmarks/block_proposer.rs | 38 +- ferveo/benches/benchmarks/pairing.rs | 74 +-- ferveo/examples/bench_primitives_size.rs | 4 +- ferveo/src/api.rs | 41 +- ferveo/src/dkg.rs | 83 +--- ferveo/src/dkg/common.rs | 10 +- ferveo/src/dkg/pv.rs | 67 +-- ferveo/src/lib.rs | 29 +- ferveo/src/primitives.rs | 21 +- ferveo/src/vss.rs | 30 +- ferveo/src/vss/pvss.rs | 157 +++--- subproductdomain/Cargo.toml | 12 +- subproductdomain/src/lib.rs | 162 ++++--- tpke-wasm/Cargo.toml | 11 +- tpke-wasm/src/lib.rs | 4 +- tpke/Cargo.toml | 15 +- tpke/benches/arkworks.rs | 133 ++--- tpke/benches/tpke.rs | 25 +- tpke/src/api.rs | 28 +- tpke/src/ciphertext.rs | 110 +++-- tpke/src/combine.rs | 76 +-- tpke/src/context.rs | 33 +- tpke/src/decryption.rs | 145 +++--- tpke/src/hash_to_curve.rs | 25 +- tpke/src/key_share.rs | 48 +- tpke/src/lib.rs | 135 +++--- tpke/src/refresh.rs | 66 +-- 34 files changed, 1129 insertions(+), 1120 deletions(-) rename {tpke => ferveo-common}/src/serialization.rs (90%) diff --git a/Cargo.lock b/Cargo.lock index 050ab068..4697974c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,6 +38,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", + "version_check", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -55,46 +66,52 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anyhow" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "ark-bls12-381" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65be532f9dd1e98ad0150b037276cde464c6f371059e6dd02c0222395761f6aa" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" dependencies = [ "ark-ec", "ark-ff", + "ark-serialize", "ark-std", ] [[package]] name = "ark-ec" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea978406c4b1ca13c2db2373b05cc55429c3575b8b21f1b9ee859aa5b03dd42" +checksum = "52d7f0c52aff14f216200a9eee06a9990fee2e51fc9599e226df448ad3232886" dependencies = [ "ark-ff", + "ark-poly", "ark-serialize", "ark-std", "derivative", + "hashbrown 0.13.2", + "itertools", "num-traits", "zeroize", ] [[package]] name = "ark-ff" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +checksum = "51ee31d8869a353433524dbd5a8f51f95cdafe7c66d458956ec13aa737198562" dependencies = [ "ark-ff-asm", "ark-ff-macros", "ark-serialize", "ark-std", "derivative", + "digest 0.10.6", + "itertools", "num-bigint", "num-traits", "paste", @@ -104,9 +121,9 @@ dependencies = [ [[package]] name = "ark-ff-asm" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +checksum = "3fc8f7ec7fdcc20f3f110783c043d80479b42f500003cf92b71ca90f34a2ba0e" dependencies = [ "quote", "syn", @@ -114,45 +131,47 @@ dependencies = [ [[package]] name = "ark-ff-macros" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +checksum = "15aa320e38052d644e569740bad208e5f9f5fafedcc9e6b1557f723be1b7ff8d" dependencies = [ "num-bigint", "num-traits", + "proc-macro2", "quote", "syn", ] [[package]] name = "ark-poly" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0f78f47537c2f15706db7e98fe64cc1711dbf9def81218194e17239e53e5aa" +checksum = "88d2e8741caf33ab3063f1fc65617716ffb18cba8e872998aa2eef0d4e4b56d1" dependencies = [ "ark-ff", "ark-serialize", "ark-std", "derivative", - "hashbrown 0.11.2", + "hashbrown 0.13.2", ] [[package]] name = "ark-serialize" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +checksum = "58ea39d00a8a4c832e6f6520e58ccec7bf909c4845863512e9b8656fd47df355" dependencies = [ "ark-serialize-derive", "ark-std", - "digest 0.9.0", + "digest 0.10.6", + "num-bigint", ] [[package]] name = "ark-serialize-derive" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd4e5f0bf8285d5ed538d27fab7411f3e297908fd93c62195de8bee3f199e82" +checksum = "101333772a4020c883890811500d5ecc704c545a90140629af5c3b9f00d78953" dependencies = [ "proc-macro2", "quote", @@ -161,9 +180,9 @@ dependencies = [ [[package]] name = "ark-std" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", "rand 0.8.5", @@ -175,15 +194,6 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -dependencies = [ - "nodrop", -] - [[package]] name = "arrayvec" version = "0.7.2" @@ -196,7 +206,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -245,12 +255,12 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "blake2b_simd" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127" +checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" dependencies = [ "arrayref", - "arrayvec 0.7.2", + "arrayvec", "constant_time_eq", ] @@ -286,9 +296,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "bytemuck" @@ -310,9 +320,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.77" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -455,9 +465,9 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.1.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" [[package]] name = "core-foundation-sys" @@ -646,9 +656,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.82" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" +checksum = "90d59d9acd2a682b4e40605a242f6670eaa58c5957471cbf85e8aa6a0b97a5e8" dependencies = [ "cc", "cxxbridge-flags", @@ -658,9 +668,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.82" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" +checksum = "ebfa40bda659dd5c864e65f4c9a2b0aff19bea56b017b9b77c73d3766a453a38" dependencies = [ "cc", "codespan-reporting", @@ -673,15 +683,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.82" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" +checksum = "457ce6757c5c70dc6ecdbda6925b958aae7f959bda7d8fb9bde889e34a09dc03" [[package]] name = "cxxbridge-macro" -version = "1.0.82" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" +checksum = "ebf883b7aacd7b2aeb2a7b338648ee19f57c140d4ee8e52c68979c6b2f7f2263" dependencies = [ "proc-macro2", "quote", @@ -690,9 +700,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" +checksum = "c0808e1bd8671fb44a113a14e13497557533369847788fa2ae912b6ebfce9fa8" dependencies = [ "darling_core", "darling_macro", @@ -700,9 +710,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" +checksum = "001d80444f28e193f30c2f293455da62dcf9a6b29918a4253152ae2b1de592cb" dependencies = [ "fnv", "ident_case", @@ -714,9 +724,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" +checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685" dependencies = [ "darling_core", "quote", @@ -775,9 +785,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" dependencies = [ "serde", "signature", @@ -801,9 +811,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "fastrand" @@ -842,6 +852,7 @@ dependencies = [ "rand_core 0.6.4", "serde", "serde_bytes", + "serde_with", "subproductdomain", "subtle", "zeroize", @@ -851,15 +862,14 @@ dependencies = [ name = "ferveo-common" version = "0.1.0" dependencies = [ - "anyhow", "ark-bls12-381", "ark-ec", "ark-serialize", "ark-std", "bincode", "serde", - "serde_bytes", "serde_json", + "serde_with", ] [[package]] @@ -870,7 +880,7 @@ dependencies = [ "ferveo", "group-threshold-cryptography", "pyo3", - "pyo3-build-config", + "pyo3-build-config 0.18.1", "rand 0.8.5", ] @@ -964,7 +974,6 @@ dependencies = [ "miracl_core", "rand 0.8.5", "rand_core 0.6.4", - "rayon", "rust-crypto", "serde", "serde_with", @@ -980,18 +989,18 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] [[package]] name = "hermit-abi" @@ -1002,6 +1011,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -1051,9 +1069,9 @@ dependencies = [ [[package]] name = "indoc" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adab1eaa3408fb7f0c777a73e7465fd5656136fc93b670eb6df3c88c2c1344e3" +checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" [[package]] name = "inferno" @@ -1061,10 +1079,10 @@ version = "0.10.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3886428c6400486522cf44b8626e7b94ad794c14390290f2a274dcf728a58f" dependencies = [ - "ahash", + "ahash 0.7.6", "atty", "indexmap", - "itoa 1.0.4", + "itoa 1.0.5", "lazy_static", "log", "num-format", @@ -1111,15 +1129,15 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -1141,15 +1159,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.137" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "link-cplusplus" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ "cc", ] @@ -1262,12 +1280,6 @@ dependencies = [ "memoffset 0.6.5", ] -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - [[package]] name = "num-bigint" version = "0.4.3" @@ -1281,12 +1293,12 @@ dependencies = [ [[package]] name = "num-format" -version = "0.4.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "arrayvec 0.4.12", - "itoa 0.4.8", + "arrayvec", + "itoa 1.0.5", ] [[package]] @@ -1310,11 +1322,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] @@ -1329,9 +1341,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "oorandom" @@ -1359,14 +1371,24 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.7", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if 1.0.0", "instant", @@ -1377,19 +1399,23 @@ dependencies = [ ] [[package]] -name = "paste" -version = "1.0.9" +name = "parking_lot_core" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] [[package]] -name = "pest" -version = "2.1.3" +name = "paste" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -dependencies = [ - "ucd-trie", -] +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" [[package]] name = "plotters" @@ -1445,7 +1471,7 @@ dependencies = [ "libc", "log", "nix", - "parking_lot", + "parking_lot 0.11.2", "smallvec", "symbolic-demangle", "tempfile", @@ -1460,9 +1486,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -1477,8 +1503,8 @@ dependencies = [ "indoc", "libc", "memoffset 0.6.5", - "parking_lot", - "pyo3-build-config", + "parking_lot 0.12.1", + "pyo3-build-config 0.17.3", "pyo3-ffi", "pyo3-macros", "unindent", @@ -1494,6 +1520,16 @@ dependencies = [ "target-lexicon", ] +[[package]] +name = "pyo3-build-config" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75439f995d07ddfad42b192dfcf3bc66a7ecfd8b4a1f5f6f046aa5c2c5d7677d" +dependencies = [ + "once_cell", + "target-lexicon", +] + [[package]] name = "pyo3-ffi" version = "0.17.3" @@ -1501,7 +1537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f6cb136e222e49115b3c51c32792886defbfb0adead26a688142b346a0b9ffc" dependencies = [ "libc", - "pyo3-build-config", + "pyo3-build-config 0.17.3", ] [[package]] @@ -1538,9 +1574,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -1656,20 +1692,19 @@ dependencies = [ [[package]] name = "rayon" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" dependencies = [ - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -1697,9 +1732,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "regex-syntax", ] @@ -1744,7 +1779,7 @@ dependencies = [ "libc", "rand 0.3.23", "rustc-serialize", - "time 0.1.44", + "time 0.1.45", ] [[package]] @@ -1761,18 +1796,18 @@ checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" [[package]] name = "rustc_version" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ "semver", ] [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "same-file" @@ -1797,42 +1832,30 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" [[package]] name = "semver" -version = "0.11.0" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "serde" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.7" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" +checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" dependencies = [ "serde", ] @@ -1849,9 +1872,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -1860,20 +1883,20 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.89" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ - "itoa 1.0.4", + "itoa 1.0.5", "ryu", "serde", ] [[package]] name = "serde_with" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bf4a5a814902cd1014dbccfa4d4560fb8432c779471e96e035602519f82eef" +checksum = "30d904179146de381af4c93d3af6ca4984b3152db687dacb9c3c35e86f39809c" dependencies = [ "base64", "chrono", @@ -1887,9 +1910,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3452b4c0f6c1e357f73fdb87cd1efabaa12acf328c7a528e252893baeb3f4aa" +checksum = "a1966009f3c05f095697c537312f5415d1e3ed31ce0a56942bac4c771c5c335e" dependencies = [ "darling", "proc-macro2", @@ -1984,9 +2007,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.103" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -2007,9 +2030,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" +checksum = "8ae9980cab1db3fceee2f6c6f643d5d8de2997c58ee8d25fb0cc8a9e9e7348e5" [[package]] name = "tempfile" @@ -2027,9 +2050,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -2071,9 +2094,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", @@ -2086,7 +2109,7 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ - "itoa 1.0.4", + "itoa 1.0.5", "serde", "time-core", "time-macros", @@ -2123,7 +2146,7 @@ version = "0.1.0" dependencies = [ "group-threshold-cryptography", "pyo3", - "pyo3-build-config", + "pyo3-build-config 0.18.1", ] [[package]] @@ -2137,6 +2160,7 @@ dependencies = [ "ark-std", "bincode", "console_error_panic_hook", + "ferveo-common", "getrandom 0.2.8", "group-threshold-cryptography", "rand 0.8.5", @@ -2150,21 +2174,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "ucd-trie" -version = "0.1.5" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-width" @@ -2180,9 +2198,9 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "unindent" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ee9362deb4a96cef4d437d1ad49cffc9b9e92d202b6995674e928ce684f112" +checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" [[package]] name = "universal-hash" @@ -2237,9 +2255,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "serde", @@ -2249,9 +2267,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", @@ -2264,9 +2282,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -2276,9 +2294,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2286,9 +2304,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -2299,15 +2317,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "wasm-bindgen-test" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d2fff962180c3fadf677438054b1db62bee4aa32af26a45388af07d1287e1d" +checksum = "6db36fc0f9fb209e88fb3642590ae0205bb5a56216dabd963ba15879fe53a30b" dependencies = [ "console_error_panic_hook", "js-sys", @@ -2319,9 +2337,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4683da3dfc016f704c9f82cf401520c4f1cb3ee440f7f52b3d6ac29506a49ca7" +checksum = "0734759ae6b3b1717d661fe4f016efcfb9828f5edb4520c18eaee05af3b43be9" dependencies = [ "proc-macro2", "quote", @@ -2329,9 +2347,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -2380,6 +2398,72 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + [[package]] name = "zeroize" version = "1.5.7" @@ -2391,9 +2475,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" dependencies = [ "proc-macro2", "quote", diff --git a/ferveo-common/Cargo.toml b/ferveo-common/Cargo.toml index 6582ab1a..873b0f18 100644 --- a/ferveo-common/Cargo.toml +++ b/ferveo-common/Cargo.toml @@ -6,18 +6,17 @@ license = "GPL-3.0" authors = ["Heliax AG "] [dependencies] -anyhow = "1.0.47" -ark-std = "0.3" -ark-ec = "0.3" +ark-std = "0.4" +ark-ec = "0.4" serde = { version = "1.0", features = ["derive"] } -ark-serialize = {version = "0.3", features = ["derive"]} -serde_bytes = "0.11" +ark-serialize = {version = "0.4", features = ["derive"]} +serde_with = "2.2.0" [dev-dependencies] -ark-bls12-381 = "0.3" +ark-bls12-381 = "0.4" serde_json = "1.0" bincode = "1.0" [profile.release] opt-level = 3 -lto = true \ No newline at end of file +lto = true diff --git a/ferveo-common/src/keypair.rs b/ferveo-common/src/keypair.rs index 8feac538..756eccee 100644 --- a/ferveo-common/src/keypair.rs +++ b/ferveo-common/src/keypair.rs @@ -1,17 +1,19 @@ -use ark_ec::PairingEngine; -use ark_ec::{AffineCurve, ProjectiveCurve}; -use ark_serialize::{ - CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write, -}; +use std::ops::Mul; + +use ark_ec::pairing::Pairing; +use ark_ec::{AffineRepr, CurveGroup}; use ark_std::rand::RngCore; use serde::*; +use serde_with::serde_as; + +use crate::serialization; #[derive(Copy, Clone, Debug)] -pub struct PreparedPublicKey { +pub struct PreparedPublicKey { pub encryption_key: E::G2Prepared, } -impl From> for PreparedPublicKey { +impl From> for PreparedPublicKey { fn from(value: PublicKey) -> Self { PreparedPublicKey:: { encryption_key: E::G2Prepared::from(value.encryption_key), @@ -19,51 +21,33 @@ impl From> for PreparedPublicKey { } } -#[derive( - Copy, - Clone, - Debug, - Eq, - PartialEq, - Serialize, - Deserialize, - CanonicalSerialize, - CanonicalDeserialize, -)] -pub struct PublicKey { - #[serde(with = "crate::ark_serde")] +#[serde_as] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct PublicKey { + #[serde_as(as = "serialization::SerdeAs")] pub encryption_key: E::G2Affine, } -impl Default for PublicKey { +impl Default for PublicKey { fn default() -> Self { Self { - encryption_key: E::G2Affine::prime_subgroup_generator(), + encryption_key: E::G2Affine::generator(), } } } -#[derive( - Clone, - Copy, - Debug, - Eq, - PartialEq, - Serialize, - Deserialize, - CanonicalSerialize, - CanonicalDeserialize, -)] -pub struct Keypair { - #[serde(with = "crate::ark_serde")] - pub decryption_key: E::Fr, +#[serde_as] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct Keypair { + #[serde_as(as = "serialization::SerdeAs")] + pub decryption_key: E::ScalarField, } -impl Keypair { +impl Keypair { /// Returns the public session key for the publicly verifiable DKG participant pub fn public(&self) -> PublicKey { PublicKey:: { - encryption_key: E::G2Affine::prime_subgroup_generator() + encryption_key: E::G2Affine::generator() .mul(self.decryption_key) .into_affine(), } @@ -73,7 +57,7 @@ impl Keypair { pub fn new(rng: &mut R) -> Self { use ark_std::UniformRand; Self { - decryption_key: E::Fr::rand(rng), + decryption_key: E::ScalarField::rand(rng), } } } diff --git a/ferveo-common/src/lib.rs b/ferveo-common/src/lib.rs index b437bdf7..f05e3ea3 100644 --- a/ferveo-common/src/lib.rs +++ b/ferveo-common/src/lib.rs @@ -1,72 +1,25 @@ -use anyhow::Result; -use ark_ec::PairingEngine; -use ark_serialize::{ - CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write, -}; +use ark_ec::pairing::Pairing; pub mod keypair; +pub mod serialization; + pub use keypair::*; +pub use serialization::*; -#[derive(Clone, Debug, CanonicalSerialize, CanonicalDeserialize, PartialEq)] +#[derive(Clone, Debug, PartialEq)] /// Represents an external validator -pub struct ExternalValidator { +pub struct ExternalValidator { /// The established address of the validator pub address: String, /// The Public key pub public_key: PublicKey, } -#[derive(Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] -pub struct Validator { +#[derive(Clone, Debug)] +pub struct Validator { pub validator: ExternalValidator, pub share_index: usize, } +// TODO: Do we want to use this trait? Why? pub trait Rng: ark_std::rand::CryptoRng + ark_std::rand::RngCore {} - -pub mod ark_serde { - use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; - use serde_bytes::{Deserialize, Serialize}; - - /// Serialize an ark type with serde - pub fn serialize(data: &T, serializer: S) -> Result - where - S: serde::Serializer, - T: CanonicalSerialize + std::fmt::Debug, - { - use serde::ser::Error; - let mut bytes = vec![]; - data.serialize(&mut bytes).map_err(Error::custom)?; - serde_bytes::Bytes::new(&bytes).serialize(serializer) - } - /// Deserialize an ark type with serde - pub fn deserialize<'d, D, T>(deserializer: D) -> Result - where - D: serde::Deserializer<'d>, - T: CanonicalDeserialize, - { - use serde::de::Error; - let bytes = ::deserialize(deserializer)?; - T::deserialize(bytes.as_slice()).map_err(Error::custom) - } -} - -#[test] -fn test_ark_serde() { - use ark_bls12_381::G1Affine; - use ark_ec::AffineCurve; - use serde::{Deserialize, Serialize}; - - #[derive(Serialize, Deserialize)] - struct Test { - #[serde(with = "ark_serde")] - pub p: G1Affine, - } - - let p = G1Affine::prime_subgroup_generator(); - let t = Test { p }; - let m = serde_json::to_string(&t).unwrap(); - let _t2: Test = serde_json::from_str(&m).unwrap(); - let m = bincode::serialize(&t).unwrap(); - let _t2: Test = bincode::deserialize(&m).unwrap(); -} diff --git a/tpke/src/serialization.rs b/ferveo-common/src/serialization.rs similarity index 90% rename from tpke/src/serialization.rs rename to ferveo-common/src/serialization.rs index f9496c92..d8953481 100644 --- a/tpke/src/serialization.rs +++ b/ferveo-common/src/serialization.rs @@ -28,7 +28,7 @@ pub mod ser { S: serde::Serializer, { let mut bytes = vec![]; - val.serialize(&mut bytes) + val.serialize_uncompressed(&mut bytes) .map_err(serde::ser::Error::custom)?; Bytes::serialize_as(&bytes, serializer) @@ -42,7 +42,8 @@ pub mod ser { D: serde::Deserializer<'de>, { let bytes: Vec = Bytes::deserialize_as(deserializer)?; - T::deserialize(&mut &bytes[..]).map_err(serde::de::Error::custom) + T::deserialize_uncompressed(&mut &bytes[..]) + .map_err(serde::de::Error::custom) } } @@ -65,7 +66,7 @@ where S: serde::Serializer, { let mut bytes = vec![]; - val.serialize(&mut bytes) + val.serialize_uncompressed(&mut bytes) .map_err(serde::ser::Error::custom)?; Bytes::serialize_as(&bytes, serializer) @@ -81,6 +82,7 @@ where D: serde::Deserializer<'de>, { let bytes: Vec = Bytes::deserialize_as(deserializer)?; - T::deserialize(&mut &bytes[..]).map_err(serde::de::Error::custom) + T::deserialize_uncompressed(&mut &bytes[..]) + .map_err(serde::de::Error::custom) } } diff --git a/ferveo/Cargo.lock b/ferveo/Cargo.lock index 6838c84f..dce2b0bd 100644 --- a/ferveo/Cargo.lock +++ b/ferveo/Cargo.lock @@ -386,7 +386,7 @@ dependencies = [ [[package]] name = "bls12_381" -version = "0.4.0" +version = "0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c56609cc42c628848e7b18e0baf42a4ef626b8c50442dc08b8094bd21d8ad32" dependencies = [ @@ -1141,7 +1141,7 @@ checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] name = "num" -version = "0.4.0" +version = "0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" dependencies = [ @@ -1155,7 +1155,7 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.0" +version = "0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e0d047c1062aa51e256408c560894e5251f08925980e53cf1aa5bd00eec6512" dependencies = [ @@ -1166,7 +1166,7 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.0" +version = "0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" dependencies = [ @@ -1175,7 +1175,7 @@ dependencies = [ [[package]] name = "num-format" -version = "0.4.0" +version = "0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" dependencies = [ @@ -1206,7 +1206,7 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.0" +version = "0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" dependencies = [ @@ -1525,7 +1525,7 @@ dependencies = [ [[package]] name = "redjubjub" -version = "0.4.0" +version = "0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dcf30702f15c157e348b4ccef28b1224fc7da8f8430d553bdc47b2d6599107b" dependencies = [ @@ -1943,7 +1943,7 @@ checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "universal-hash" -version = "0.4.0" +version = "0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" dependencies = [ @@ -2062,7 +2062,7 @@ dependencies = [ [[package]] name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +version = "0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" @@ -2077,7 +2077,7 @@ dependencies = [ [[package]] name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +version = "0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/ferveo/Cargo.toml b/ferveo/Cargo.toml index 8cb1ac7e..7ea51328 100644 --- a/ferveo/Cargo.toml +++ b/ferveo/Cargo.toml @@ -14,12 +14,12 @@ authors = ["Heliax AG "] group-threshold-cryptography = { path = "../tpke" } ferveo-common = { path = "../ferveo-common" } subproductdomain = { path = "../subproductdomain" } -ark-std = "0.3" -ark-bls12-381 = "0.3" -ark-ec = "0.3" -ark-ff = "0.3" -ark-serialize = "0.3" -ark-poly = "0.3" +ark-std = "0.4" +ark-bls12-381 = "0.4" +ark-ec = "0.4" +ark-ff = "0.4" +ark-serialize = "0.4" +ark-poly = "0.4" rand = "0.8" rand_old = { package = "rand", version = "0.7" } # used by benchmarks/pairing.rs either = "1.6.1" @@ -35,6 +35,7 @@ subtle = "2.4" itertools = "0.10.1" measure_time = "0.8" rand_core = "0.6.4" +serde_with = "2.0.1" [dev-dependencies] criterion = "0.3" # supports pprof, # TODO: Figure out if/how we can update to 0.4 diff --git a/ferveo/benches/benchmarks/block_proposer.rs b/ferveo/benches/benchmarks/block_proposer.rs index 95b2baae..1f18a4ee 100644 --- a/ferveo/benches/benchmarks/block_proposer.rs +++ b/ferveo/benches/benchmarks/block_proposer.rs @@ -3,7 +3,7 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; use ark_bls12_381::*; -use ark_ec::msm::FixedBaseMSM; +use ark_ec::msm::FixedBase; use ark_ec::*; use ark_ff::PrimeField; use ark_std::One; @@ -11,9 +11,9 @@ use ark_std::UniformRand; use ferveo::*; use itertools::Itertools; -type G1Prepared = ::G1Prepared; -type G2Prepared = ::G2Prepared; -type Fqk = ::Fqk; +type G1Prepared = ::G1Prepared; +type G2Prepared = ::G2Prepared; +type TargetField = ::TargetField; pub fn block_proposer(c: &mut Criterion) { let rng = &mut ark_std::test_rng(); @@ -22,17 +22,17 @@ pub fn block_proposer(c: &mut Criterion) { group.measurement_time(core::time::Duration::new(30, 0)) use ark_ff::PrimeField; - let scalar_bits = Fr::size_in_bits(); - let window_size = FixedBaseMSM::get_mul_window_size(1000); + let scalar_bits = ScalarField::size_in_bits(); + let window_size = FixedBase::get_mul_window_size(1000); let B = (0..8192) - .map(|_| G2Affine::prime_subgroup_generator().mul(Fr::rand(rng))) + .map(|_| G2Affine::generator().mul(ScalarField::rand(rng))) .collect::>(); let base_tables = B .iter() .map(|B_j| { - FixedBaseMSM::get_window_table(scalar_bits, window_size, *B_j) + FixedBase::get_window_table(scalar_bits, window_size, *B_j) }) .collect::>(); group.measurement_time(core::time::Duration::new(30, 0)) @@ -47,7 +47,7 @@ pub fn work( B: &[Vec>], window_size: usize, ) { - let scalar_bits = Fr::size_in_bits(); + let scalar_bits = ScalarField::size_in_bits(); let rng = &mut rand::thread_rng(); // e(U, H_{\mathbb{G}_2} (U)) = e(G, W) @@ -57,19 +57,19 @@ pub fn work( (G1Prepared::from(*U), G2Prepared::from(*H_G)), (G.clone(), G2Prepared::from(*W)), ]; - black_box(Bls12_381::product_of_pairings(prep.iter()) == Fqk::one()); + black_box(Bls12_381::multi_pairing(prep.iter()) == TargetField::one()); } let V = D.len(); let T = ciphertexts.len(); - let alpha = (0..V * T).map(|_| Fr::rand(rng)).collect::>(); + let alpha = (0..V * T).map(|_| ScalarField::rand(rng)).collect::>(); let prepared_alpha_U_j = G1Prepared::from( ciphertexts .iter() .zip(alpha.chunks(V)) - .map(|((U_j, _, _), alpha_j)| U_j.mul(alpha_j.iter().sum::())) - .sum::() + .map(|((U_j, _, _), alpha_j)| U_j.mul(alpha_j.iter().sum::())) + .sum::() .into_affine(), ); @@ -82,9 +82,9 @@ pub fn work( D_ij.iter() .zip(alpha.windows(T)) .map(|(D_i, alpha_i)| { - D_i.mul(alpha_i.iter().sum::()) + D_i.mul(alpha_i.iter().sum::()) }) - .sum::() + .sum::() .into_affine(), ), P_i.clone(), @@ -94,15 +94,15 @@ pub fn work( .collect::>(); // \prod_i e(\sum_{j} [\alpha_{i,j}] D_{i,j}, P_i) = e(\sum_{j} [\sum_i \alpha_{i,j} U_j], H) - black_box(Bls12_381::product_of_pairings(prepared_alpha_D_i.iter())); + black_box(Bls12_381::multi_pairing(prepared_alpha_D_i.iter())); let n = B.len() * 2 / 3; let mut u = Vec::with_capacity(n); for _ in 0..n { - u.push(Fr::rand(rng)); + u.push(ScalarField::rand(rng)); } let lagrange = ferveo::batch_inverse( - &ferveo::SubproductDomain::::new(u.clone()) + &ferveo::SubproductDomain::::new(u.clone()) .inverse_lagrange_coefficients(), ) .unwrap(); @@ -111,7 +111,7 @@ pub fn work( .iter() .zip(lagrange.iter()) .map(|(B_ij, lambda)| { - FixedBaseMSM::multi_scalar_mul::( + FixedBase::msm::( scalar_bits, window_size, &B_ij, diff --git a/ferveo/benches/benchmarks/pairing.rs b/ferveo/benches/benchmarks/pairing.rs index 46d997fc..47cce6ad 100644 --- a/ferveo/benches/benchmarks/pairing.rs +++ b/ferveo/benches/benchmarks/pairing.rs @@ -17,12 +17,12 @@ pub fn lagrange(c: &mut Criterion) { group.measurement_time(core::time::Duration::new(30, 0)); let mut u = vec![]; for _ in 0..(8192 * 2 / 3) { - u.push(Fr::rand(rng)); + u.push(ScalarField::rand(rng)); } group.bench_function("BLS12-381 Fr 8192*2/3 lagrange coefficients", |b| { b.iter(|| { black_box( - subproductdomain::SubproductDomain::::new(u.clone()) + subproductdomain::SubproductDomain::::new(u.clone()) .inverse_lagrange_coefficients(), ) }) @@ -32,13 +32,13 @@ pub fn lagrange(c: &mut Criterion) { let mut u = vec![]; for _ in 0..(8192 * 2 / 3) { - u.push(jubjub::Fr::rand(rng)); + u.push(jubjub::ScalarField::rand(rng)); } group.bench_function("Jubjub Fr 8192*2/3 lagrange coefficients", |b| { b.iter(|| { black_box( - subproductdomain::SubproductDomain::::new( + subproductdomain::SubproductDomain::::new( u.clone(), ) .inverse_lagrange_coefficients(), @@ -52,20 +52,20 @@ pub fn pairing(c: &mut Criterion) { let mut group = c.benchmark_group("pairing running time"); group.sample_size(10); - type G1Prepared = ::G1Prepared; - type G2Prepared = ::G2Prepared; + type G1Prepared = ::G1Prepared; + type G2Prepared = ::G2Prepared; let P = (0..100) .map(|_| { - G1Affine::prime_subgroup_generator() - .mul(Fr::rand(rng)) + G1Affine::generator() + .mul(ScalarField::rand(rng)) .into_affine() }) .collect::>(); let Q = (0..100) .map(|_| { - G2Affine::prime_subgroup_generator() - .mul(Fr::rand(rng)) + G2Affine::generator() + .mul(ScalarField::rand(rng)) .into_affine() }) .collect::>(); @@ -99,21 +99,21 @@ pub fn pairing(c: &mut Criterion) { black_box( P.iter().map(|i| G1Prepared::from(*i)).collect::>(), ), - black_box(Bls12_381::product_of_pairings(PQ.iter())), + black_box(Bls12_381::multi_pairing(PQ.iter())), ) }) }); group.bench_function("BLS12-381 product_of_pairing both prepared", |b| { - b.iter(|| black_box(Bls12_381::product_of_pairings(PQ.iter()))) + b.iter(|| black_box(Bls12_381::multi_pairing(PQ.iter()))) }); - let Q_j = G2Affine::prime_subgroup_generator() - .mul(Fr::rand(rng)) + let Q_j = G2Affine::generator() + .mul(ScalarField::rand(rng)) .into_affine(); - let r = Fr::rand(rng); + let r = ScalarField::rand(rng); group.bench_function("BLS12-381 100 linear combine G1", |b| { - b.iter(|| black_box(P.iter().map(|i| i.mul(r)).sum::())) + b.iter(|| black_box(P.iter().map(|i| i.mul(r)).sum::())) }); group.bench_function("BLS12-381 100 linear combine G2", |b| { @@ -122,18 +122,18 @@ pub fn pairing(c: &mut Criterion) { let P = (0..(8192 * 2 / 3)) .map(|_| { - G1Affine::prime_subgroup_generator() - .mul(Fr::rand(rng)) + G1Affine::generator() + .mul(ScalarField::rand(rng)) .into_affine() }) .collect::>(); let mut u = vec![]; for _ in 0..(8192 * 2 / 3) { - u.push(Fr::rand(rng)); + u.push(ScalarField::rand(rng)); } - let lagrange = subproductdomain::SubproductDomain::::new(u.clone()) + let lagrange = subproductdomain::SubproductDomain::::new(u.clone()) .inverse_lagrange_coefficients() .iter() .map(|x| x.inverse().unwrap()) @@ -145,21 +145,21 @@ pub fn pairing(c: &mut Criterion) { P.iter() .zip(lagrange.iter()) .map(|(i, lambda)| i.mul(*lambda)) - .sum::() + .sum::() .into_affine(), ) }) }); - use ark_ec::msm::FixedBaseMSM; - let window_size = FixedBaseMSM::get_mul_window_size(3000); + use ark_ec::msm::FixedBase; + let window_size = FixedBase::get_mul_window_size(3000); use ark_ff::PrimeField; - let scalar_bits = Fr::size_in_bits(); - let base_table = FixedBaseMSM::get_window_table( + let scalar_bits = ScalarField::size_in_bits(); + let base_table = FixedBase::get_window_table( scalar_bits, window_size, - Q_j.into_projective(), + Q_j.into_group(), ); group.measurement_time(core::time::Duration::new(30, 0)); @@ -168,7 +168,7 @@ pub fn pairing(c: &mut Criterion) { black_box( Q.iter() .map(|_| { - FixedBaseMSM::multi_scalar_mul::( + FixedBase::msm::( scalar_bits, window_size, &base_table, @@ -182,8 +182,8 @@ pub fn pairing(c: &mut Criterion) { let Q = (0..(8192 * 2 / 3)) .map(|_| { - G2Affine::prime_subgroup_generator() - .mul(Fr::rand(rng)) + G2Affine::generator() + .mul(ScalarField::rand(rng)) .into_affine() }) .collect::>(); @@ -198,10 +198,10 @@ pub fn pairing(c: &mut Criterion) { let _base_tables = Q .iter() .map(|q| { - FixedBaseMSM::get_window_table( + FixedBase::get_window_table( scalar_bits, window_size, - q.into_projective(), + q.into_group(), ) }) .collect::>(); @@ -212,7 +212,7 @@ pub fn pairing(c: &mut Criterion) { Q.iter() .zip(lagrange.iter()) .map(|(_, lambda)| { - FixedBaseMSM::multi_scalar_mul::( + FixedBase::msm::( scalar_bits, window_size, &base_table, @@ -227,17 +227,17 @@ pub fn pairing(c: &mut Criterion) { use ark_ed_on_bls12_381 as jubjub; let P = (0..(8192 * 2 / 3)) .map(|_| { - jubjub::EdwardsAffine::prime_subgroup_generator() - .mul(jubjub::Fr::rand(rng)) + jubjub::EdwardsAffine::generator() + .mul(jubjub::ScalarField::rand(rng)) .into_affine() }) .collect::>(); let mut u = vec![]; for _ in 0..(8192 * 2 / 3) { - u.push(jubjub::Fr::rand(rng)); + u.push(jubjub::ScalarField::rand(rng)); } - /*let lagrange = ferveo::SubproductDomain::::new(u.clone()) + /*let lagrange = ferveo::SubproductDomain::::new(u.clone()) .inverse_lagrange_coefficients() .iter() .map(|x| x.inverse().unwrap()) @@ -359,7 +359,7 @@ pub fn bench_batch_inverse(c: &mut Criterion) { let rng = &mut ark_std::test_rng(); let n = 8192 * 2 / 3; let a = (0..n) - .map(|_| ark_bls12_381::Fr::rand(rng)) + .map(|_| ark_bls12_381::ScalarField::rand(rng)) .collect::>(); let mut group = c.benchmark_group("BLS12-381 Batch inverse"); diff --git a/ferveo/examples/bench_primitives_size.rs b/ferveo/examples/bench_primitives_size.rs index 6c09f1c1..ef8dc097 100644 --- a/ferveo/examples/bench_primitives_size.rs +++ b/ferveo/examples/bench_primitives_size.rs @@ -4,7 +4,6 @@ use std::io::prelude::*; use std::path::PathBuf; use ark_bls12_381::Bls12_381 as EllipticCurve; -use ark_serialize::CanonicalSerialize; use ferveo::*; use ferveo_common::ExternalValidator; use itertools::iproduct; @@ -131,8 +130,7 @@ fn main() { for (shares_num, threshold) in configs { println!("shares_num: {}, threshold: {}", shares_num, threshold); let dkg = setup(*shares_num as u32, threshold, rng); - let mut transcript_bytes = vec![]; - dkg.vss[&0].serialize(&mut transcript_bytes).unwrap(); + let transcript_bytes = bincode::serialize(&dkg.vss[&0]).unwrap(); save_data( *shares_num as usize, diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index 4eed5b23..4987156b 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -1,9 +1,11 @@ use ark_poly::EvaluationDomain; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use bincode::Options; +use ferveo_common::serialization::ser::serialize; use group_threshold_cryptography as tpke; use rand::rngs::StdRng; use rand::{thread_rng, RngCore, SeedableRng}; +use serde::{Deserialize, Serialize}; pub type E = ark_bls12_381::Bls12_381; @@ -43,6 +45,7 @@ pub struct G1Prepared(pub tpke::api::TpkeG1Prepared); pub struct SharedSecret(tpke::api::TpkeSharedSecret); +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Keypair(ferveo_common::Keypair); impl Keypair { @@ -55,28 +58,24 @@ impl Keypair { } pub fn from_bytes(bytes: &[u8]) -> Self { - Self(ferveo_common::Keypair::::deserialize(bytes).unwrap()) + Self(bincode::deserialize(bytes).unwrap()) } pub fn to_bytes(&self) -> Vec { - let mut buf = vec![]; - self.0.serialize(&mut buf).unwrap(); - buf + bincode::serialize(&self.0).unwrap() } } -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PublicKey(ferveo_common::PublicKey); impl PublicKey { pub fn from_bytes(bytes: &[u8]) -> Self { - Self(ferveo_common::PublicKey::::deserialize(bytes).unwrap()) + Self(bincode::deserialize(bytes).unwrap()) } pub fn to_bytes(&self) -> Vec { - let mut buf = vec![]; - self.0.serialize(&mut buf).unwrap(); - buf + bincode::serialize(&self.0).unwrap() } } @@ -92,18 +91,16 @@ impl ExternalValidator { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Transcript(crate::PubliclyVerifiableSS); impl Transcript { pub fn from_bytes(bytes: &[u8]) -> Self { - Self(crate::PubliclyVerifiableSS::::deserialize(bytes).unwrap()) + Self(bincode::deserialize(bytes).unwrap()) } pub fn to_bytes(&self) -> Vec { - let mut buf = vec![]; - self.0.serialize(&mut buf).unwrap(); - buf + bincode::serialize(&self.0).unwrap() } } @@ -175,6 +172,7 @@ pub struct UnblindingKey(tpke::api::TpkeUnblindingKey); #[derive(Clone)] pub struct DecryptionShare(tpke::api::TpkeDecryptionShareSimplePrecomputed); +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AggregatedTranscript( crate::PubliclyVerifiableSS, ); @@ -203,18 +201,11 @@ impl AggregatedTranscript { } pub fn from_bytes(bytes: &[u8]) -> Self { - Self( - crate::PubliclyVerifiableSS::::deserialize( - bytes, - ) - .unwrap(), - ) + Self(bincode::deserialize(bytes).unwrap()) } pub fn to_bytes(&self) -> Vec { - let mut buf = vec![]; - self.0.serialize(&mut buf).unwrap(); - buf + bincode::serialize(&self.0).unwrap() } } @@ -223,8 +214,8 @@ mod test_ferveo_api { use std::collections::HashMap; use std::fmt::format; - use ark_bls12_381::{Bls12_381 as E, Fr, G2Projective}; - use ark_ec::ProjectiveCurve; + use ark_bls12_381::{Bls12_381 as E, G2Projective}; + use ark_ec::CurveGroup; use ark_poly::EvaluationDomain; use ark_serialize::CanonicalSerialize; use ark_std::UniformRand; diff --git a/ferveo/src/dkg.rs b/ferveo/src/dkg.rs index d2963144..c76a5d09 100644 --- a/ferveo/src/dkg.rs +++ b/ferveo/src/dkg.rs @@ -3,16 +3,17 @@ #![allow(unused_imports)] use anyhow::anyhow; -use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ec::pairing::Pairing; +use ark_ec::CurveGroup; use ark_ff::Zero; use ark_ff::{Field, One}; use ark_poly::{ - polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, - EvaluationDomain, Polynomial, + polynomial::univariate::DensePolynomial, EvaluationDomain, Polynomial, }; use ark_serialize::*; use bincode::Options; use ed25519_dalek as ed25519; +use serde::{Deserialize, Serialize}; pub mod common; pub mod pv; @@ -21,7 +22,7 @@ pub use common::*; pub use pv::*; // DKG parameters -#[derive(Copy, Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct Params { // TODO: Rename to ritual_id? pub tau: u64, @@ -30,81 +31,9 @@ pub struct Params { } #[derive(Debug, Clone)] -pub enum DkgState { +pub enum DkgState { Sharing { accumulated_shares: u32, block: u32 }, Dealt, Success { final_key: E::G1Affine }, Invalid, } - -impl CanonicalSerialize for DkgState { - #[inline] - fn serialize( - &self, - mut writer: W, - ) -> Result<(), SerializationError> { - match self { - Self::Sharing { - accumulated_shares, - block, - } => { - CanonicalSerialize::serialize(&0u8, &mut writer)?; - CanonicalSerialize::serialize( - &(*accumulated_shares, *block), - &mut writer, - ) - } - Self::Dealt => CanonicalSerialize::serialize(&1u8, &mut writer), - Self::Success { final_key } => { - CanonicalSerialize::serialize(&2u8, &mut writer)?; - final_key.serialize(&mut writer) - } - Self::Invalid => CanonicalSerialize::serialize(&3u8, &mut writer), - } - } - - #[inline] - fn serialized_size(&self) -> usize { - match self { - Self::Sharing { - accumulated_shares, - block, - } => { - 0u8.serialized_size() - + (*accumulated_shares, *block).serialized_size() - } - Self::Dealt => 1u8.serialized_size(), - Self::Success { final_key } => { - 2u8.serialized_size() + final_key.serialized_size() - } - Self::Invalid => 3u8.serialized_size(), - } - } -} - -impl CanonicalDeserialize for DkgState { - #[inline] - fn deserialize(mut reader: R) -> Result { - let variant = ::deserialize(&mut reader)?; - match variant { - 0 => { - let (accumulated_shares, block) = - <(u32, u32) as CanonicalDeserialize>::deserialize( - &mut reader, - )?; - Ok(Self::Sharing { - accumulated_shares, - block, - }) - } - 1 => Ok(Self::Dealt), - 2 => Ok(Self::Success { - final_key: ::G1Affine::deserialize( - &mut reader, - )?, - }), - 3 => Ok(Self::Invalid), - _ => Err(SerializationError::InvalidData), - } - } -} diff --git a/ferveo/src/dkg/common.rs b/ferveo/src/dkg/common.rs index d1edaa69..b4c1ec32 100644 --- a/ferveo/src/dkg/common.rs +++ b/ferveo/src/dkg/common.rs @@ -1,12 +1,10 @@ use std::collections::HashMap; use anyhow::{anyhow, Result}; -use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ec::pairing::Pairing; +use ark_ec::CurveGroup; use ark_ff::{Field, One, PrimeField, Zero}; -use ark_poly::{ - polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, - EvaluationDomain, -}; +use ark_poly::{polynomial::univariate::DensePolynomial, EvaluationDomain}; use ark_std::{end_timer, start_timer}; use ferveo_common::ExternalValidator; use ferveo_common::Rng; @@ -14,7 +12,7 @@ use itertools::{izip, zip_eq}; use measure_time::print_time; use serde::{Deserialize, Serialize}; -pub fn make_validators( +pub fn make_validators( validators: &[ExternalValidator], ) -> Vec> { validators diff --git a/ferveo/src/dkg/pv.rs b/ferveo/src/dkg/pv.rs index d771697f..ca7e41b0 100644 --- a/ferveo/src/dkg/pv.rs +++ b/ferveo/src/dkg/pv.rs @@ -4,20 +4,20 @@ use std::collections::HashMap; use anyhow::Context; use anyhow::{anyhow, Result}; use ark_ec::bn::TwistType::D; -use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ec::pairing::Pairing; +use ark_ec::{AffineRepr, CurveGroup, Group}; use ark_ff::{Field, One, PrimeField, Zero}; -use ark_poly::{ - polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, - EvaluationDomain, -}; +use ark_poly::{polynomial::univariate::DensePolynomial, EvaluationDomain}; use ark_serialize::*; use ark_std::{end_timer, start_timer}; use ferveo_common::Rng; use ferveo_common::{ExternalValidator, PublicKey}; +use group_threshold_cryptography as tpke; use itertools::{izip, zip_eq}; use measure_time::print_time; use rand::RngCore; -use serde::{Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde_with::serde_as; use crate::{ aggregate, make_validators, AggregatedPvss, DkgState, Params, @@ -28,20 +28,20 @@ use crate::{ // TODO: Consider removing Clone to avoid accidentally NOT-mutating state. // Currently, we're assuming that the DKG is only mutated by the owner of the instance. // Consider removing Clone after finalizing ferveo::api -#[derive(Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] -pub struct PubliclyVerifiableDkg { +#[derive(Clone, Debug)] +pub struct PubliclyVerifiableDkg { pub params: Params, pub pvss_params: PubliclyVerifiableParams, // TODO: What is session_keypair? pub session_keypair: ferveo_common::Keypair, pub validators: Vec>, pub vss: BTreeMap>, - pub domain: ark_poly::Radix2EvaluationDomain, + pub domain: ark_poly::Radix2EvaluationDomain, pub state: DkgState, pub me: usize, } -impl PubliclyVerifiableDkg { +impl PubliclyVerifiableDkg { /// Create a new DKG context to participate in the DKG /// Every identity in the DKG is linked to an ed25519 public key; /// `validators`: List of validators @@ -55,7 +55,7 @@ impl PubliclyVerifiableDkg { session_keypair: ferveo_common::Keypair, ) -> Result { use ark_std::UniformRand; - let domain = ark_poly::Radix2EvaluationDomain::::new( + let domain = ark_poly::Radix2EvaluationDomain::::new( params.shares_num as usize, ) .ok_or_else(|| anyhow!("unable to construct domain"))?; @@ -71,8 +71,8 @@ impl PubliclyVerifiableDkg { session_keypair, params, pvss_params: PubliclyVerifiableParams:: { - g: E::G1Projective::prime_subgroup_generator(), - h: E::G2Projective::prime_subgroup_generator(), + g: E::G1::generator(), + h: E::G2::generator(), }, vss: BTreeMap::new(), domain, @@ -107,7 +107,7 @@ impl PubliclyVerifiableDkg { rng: &mut R, ) -> Result> { use ark_std::UniformRand; - Pvss::::new(&E::Fr::rand(rng), self, rng) + Pvss::::new(&E::ScalarField::rand(rng), self, rng) } /// Aggregate all received PVSS messages into a single message, prepared to post on-chain @@ -130,8 +130,8 @@ impl PubliclyVerifiableDkg { pub fn final_key(&self) -> E::G1Affine { self.vss .values() - .map(|vss| vss.coeffs[0].into_projective()) - .sum::() + .map(|vss| vss.coeffs[0].into_group()) + .sum::() .into_affine() } @@ -244,28 +244,25 @@ impl PubliclyVerifiableDkg { } } -#[derive( - Serialize, - Deserialize, - Clone, - Debug, - CanonicalSerialize, - CanonicalDeserialize, -)] -#[serde(bound = "")] -pub struct Aggregation { - #[serde(with = "ferveo_common::ark_serde")] +#[serde_as] +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(bound( + serialize = "AggregatedPvss: Serialize", + deserialize = "AggregatedPvss: DeserializeOwned" +))] +pub struct Aggregation { vss: AggregatedPvss, - #[serde(with = "ferveo_common::ark_serde")] + #[serde_as(as = "ferveo_common::serialization::SerdeAs")] final_key: E::G1Affine, } #[derive(Serialize, Deserialize, Clone, Debug)] -#[serde(bound = "")] -pub enum Message { - #[serde(with = "ferveo_common::ark_serde")] +#[serde(bound( + serialize = "AggregatedPvss: Serialize, Pvss: Serialize", + deserialize = "AggregatedPvss: DeserializeOwned, Pvss: DeserializeOwned" +))] +pub enum Message { Deal(Pvss), - #[serde(with = "ferveo_common::ark_serde")] Aggregate(Aggregation), } @@ -277,7 +274,7 @@ pub(crate) mod test_common { pub use super::*; - pub type G1 = ::G1Affine; + pub type G1 = ::G1Affine; pub fn gen_n_keypairs( n: u32, @@ -414,6 +411,8 @@ mod test_dkg_init { /// Test the dealing phase of the DKG #[cfg(test)] mod test_dealing { + use ark_ec::AffineRepr; + use super::test_common::*; use crate::DkgState::Dealt; @@ -628,6 +627,8 @@ mod test_dealing { /// Test aggregating transcripts into final key #[cfg(test)] mod test_aggregation { + use ark_ec::AffineRepr; + use super::test_common::*; /// Test that if the security threshold is diff --git a/ferveo/src/lib.rs b/ferveo/src/lib.rs index 25252d8e..18b6e5cc 100644 --- a/ferveo/src/lib.rs +++ b/ferveo/src/lib.rs @@ -3,7 +3,7 @@ pub mod api; pub mod dkg; pub mod primitives; -pub mod vss; +mod vss; pub use dkg::*; pub use primitives::*; @@ -18,16 +18,11 @@ mod test_dkg_full { Bls12_381 as E, Bls12_381, Fr, G1Affine, G2Projective, }; use ark_ec::bls12::G2Affine; - use ark_ec::group::Group; - use ark_ec::{ - msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve, - }; + use ark_ec::pairing::Pairing; + use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::{Field, One, PrimeField, Zero}; use ark_ff::{Fp12, UniformRand}; - use ark_poly::{ - polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, - EvaluationDomain, - }; + use ark_poly::{polynomial::univariate::DensePolynomial, EvaluationDomain}; use ark_std::test_rng; use ark_std::{end_timer, start_timer}; use ferveo_common::Rng; @@ -46,7 +41,7 @@ mod test_dkg_full { use super::*; use crate::dkg::pv::test_common::*; - type Fqk = ::Fqk; + type TargetField = ::TargetField; fn make_shared_secret_simple_tdec( dkg: &PubliclyVerifiableDkg, @@ -56,7 +51,7 @@ mod test_dkg_full { ) -> ( PubliclyVerifiableSS, Vec>, - Fqk, + TargetField, ) { // Make sure validators are in the same order dkg is by comparing their public keys dkg.validators @@ -110,7 +105,7 @@ mod test_dkg_full { let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); let public_key = dkg.final_key(); - let ciphertext = tpke::encrypt::<_, E>(msg, aad, &public_key, rng); + let ciphertext = tpke::encrypt::(msg, aad, &public_key, rng); let validator_keypairs = gen_n_keypairs(4); let (_, _, shared_secret) = make_shared_secret_simple_tdec( @@ -138,7 +133,7 @@ mod test_dkg_full { let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); let public_key = dkg.final_key(); - let ciphertext = tpke::encrypt::<_, E>(msg, aad, &public_key, rng); + let ciphertext = tpke::encrypt::(msg, aad, &public_key, rng); let _g_inv = dkg.pvss_params.g_inv(); let validator_keypairs = gen_n_keypairs(4); @@ -188,7 +183,7 @@ mod test_dkg_full { let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); let public_key = dkg.final_key(); - let ciphertext = tpke::encrypt::<_, E>(msg, aad, &public_key, rng); + let ciphertext = tpke::encrypt::(msg, aad, &public_key, rng); let validator_keypairs = gen_n_keypairs(4); let (pvss_aggregated, decryption_shares, _) = @@ -220,7 +215,7 @@ mod test_dkg_full { // Should fail because of the bad decryption share let mut with_bad_decryption_share = decryption_share.clone(); - with_bad_decryption_share.decryption_share = Fqk::zero(); + with_bad_decryption_share.decryption_share = TargetField::zero(); assert!(!with_bad_decryption_share.verify( &pvss_aggregated.shares[0], &validator_keypairs[0].public().encryption_key, @@ -247,7 +242,7 @@ mod test_dkg_full { let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); let public_key = &dkg.final_key(); - let ciphertext = tpke::encrypt::<_, E>(msg, aad, public_key, rng); + let ciphertext = tpke::encrypt::(msg, aad, public_key, rng); let mut validator_keypairs = gen_n_keypairs(4); // Create an initial shared secret @@ -363,7 +358,7 @@ mod test_dkg_full { let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); let public_key = dkg.final_key(); - let ciphertext = tpke::encrypt::<_, E>(msg, aad, &public_key, rng); + let ciphertext = tpke::encrypt::(msg, aad, &public_key, rng); let validator_keypairs = gen_n_keypairs(4); let pvss_aggregated = aggregate(&dkg); diff --git a/ferveo/src/primitives.rs b/ferveo/src/primitives.rs index 72b5ebf6..a87d142c 100644 --- a/ferveo/src/primitives.rs +++ b/ferveo/src/primitives.rs @@ -1,5 +1,18 @@ -pub fn batch_to_projective( - p: &[A], -) -> Vec { - p.iter().map(|a| a.into_projective()).collect::>() +use ark_ec::pairing::Pairing; +use ark_ec::AffineRepr; + +// pub fn batch_to_projective( +// p: &[A], +// ) -> Vec { +// p.iter().map(|a| a.into_projective()).collect::>() +// } + +// TODO: Make it a trait to recreate the original batch_to_projective + +pub fn batch_to_projective_g1(p: &[E::G1Affine]) -> Vec { + p.iter().map(|a| a.into_group()).collect::>() +} + +pub fn batch_to_projective_g2(p: &[E::G2Affine]) -> Vec { + p.iter().map(|a| a.into_group()).collect::>() } diff --git a/ferveo/src/vss.rs b/ferveo/src/vss.rs index b864e0e8..2d65d650 100644 --- a/ferveo/src/vss.rs +++ b/ferveo/src/vss.rs @@ -3,12 +3,9 @@ pub mod pvss; use std::collections::HashMap; use anyhow::{anyhow, Result}; -use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ec::CurveGroup; use ark_ff::{Field, One, PrimeField, Zero}; -use ark_poly::{ - polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, - EvaluationDomain, -}; +use ark_poly::{polynomial::univariate::DensePolynomial, EvaluationDomain}; use ark_std::{end_timer, start_timer}; use ferveo_common::Rng; use itertools::{izip, zip_eq}; @@ -16,14 +13,15 @@ use measure_time::print_time; pub use pvss::*; use serde::{Deserialize, Serialize}; -/// The possible States of a VSS instance -#[derive(Clone, Debug)] -pub enum VssState { - /// The VSS is currently in a Sharing state with weight_ready - /// of participants signaling Ready for this VSS - Sharing { weight_ready: u32 }, - /// The VSS has completed Successfully with final secret commitment g^{\phi(0)} - Success { final_secret: Affine }, - /// The VSS has ended in Failure - Failure, -} +// TODO: Figure out if you need to / can use this struct +// /// The possible States of a VSS instance +// #[derive(Clone, Debug)] +// pub enum VssState { +// /// The VSS is currently in a Sharing state with weight_ready +// /// of participants signaling Ready for this VSS +// Sharing { weight_ready: u32 }, +// /// The VSS has completed Successfully with final secret commitment g^{\phi(0)} +// Success { final_secret: Affine }, +// /// The VSS has ended in Failure +// Failure, +// } diff --git a/ferveo/src/vss/pvss.rs b/ferveo/src/vss/pvss.rs index 71b4bc8d..edf7e29a 100644 --- a/ferveo/src/vss/pvss.rs +++ b/ferveo/src/vss/pvss.rs @@ -1,44 +1,46 @@ use std::collections::BTreeMap; use std::collections::HashMap; use std::marker::PhantomData; -use std::ops::Add; +use std::ops::{Add, Mul}; use anyhow::{anyhow, Result}; use ark_ec::bn::G2Affine; -use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve}; +use ark_ec::pairing::Pairing; +use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::UniformRand; use ark_ff::{Field, One, PrimeField, Zero}; -use ark_poly::{ - polynomial::univariate::DensePolynomial, polynomial::UVPolynomial, - EvaluationDomain, -}; +use ark_poly::DenseUVPolynomial; +use ark_poly::{polynomial::univariate::DensePolynomial, EvaluationDomain}; use ark_serialize::*; use ark_std::{end_timer, start_timer}; use ferveo_common::Rng; use ferveo_common::{Keypair, PublicKey}; -use group_threshold_cryptography::{ - prepare_combine_simple, refresh_private_key_share, - update_share_for_recovery, Ciphertext, DecryptionShareFast, - DecryptionShareSimple, DecryptionShareSimplePrecomputed, PrivateKeyShare, -}; +use group_threshold_cryptography as tpke; use itertools::izip; use itertools::{zip_eq, Itertools}; use measure_time::print_time; use rand::RngCore; -use serde::{Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde_with::serde_as; use subproductdomain::fast_multiexp; +use tpke::{ + prepare_combine_simple, refresh_private_key_share, + update_share_for_recovery, Ciphertext, DecryptionShareFast, + DecryptionShareSimple, DecryptionShareSimplePrecomputed, PrivateKeyShare, +}; -use crate::{batch_to_projective, PubliclyVerifiableDkg}; +use crate::PubliclyVerifiableDkg; +use crate::{batch_to_projective_g1, batch_to_projective_g2}; /// These are the blinded evaluations of shares of a single random polynomial -pub type ShareEncryptions = ::G2Affine; +pub type ShareEncryptions = ::G2Affine; /// Marker struct for unaggregated PVSS transcripts -#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] pub struct Unaggregated; /// Marker struct for aggregated PVSS transcripts -#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] pub struct Aggregated; /// Trait gate used to add extra methods to aggregated PVSS transcripts @@ -54,30 +56,35 @@ pub type Pvss = PubliclyVerifiableSS; pub type AggregatedPvss = PubliclyVerifiableSS; /// The choice of group generators -#[derive(Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] -pub struct PubliclyVerifiableParams { - pub g: E::G1Projective, - pub h: E::G2Projective, +#[derive(Clone, Debug)] +pub struct PubliclyVerifiableParams { + pub g: E::G1, + pub h: E::G2, } -impl PubliclyVerifiableParams { +impl PubliclyVerifiableParams { pub fn g_inv(&self) -> E::G1Prepared { - E::G1Prepared::from(-self.g.into_affine()) + E::G1Prepared::from(-self.g) } } /// Each validator posts a transcript to the chain. Once enough /// validators have done this (their total voting power exceeds /// 2/3 the total), this will be aggregated into a final key -#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq)] -pub struct PubliclyVerifiableSS { +#[serde_as] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +pub struct PubliclyVerifiableSS { /// Used in Feldman commitment to the VSS polynomial, F = g^{\phi} + #[serde_as(as = "ferveo_common::serialization::SerdeAs")] pub coeffs: Vec, /// The shares to be dealt to each validator - pub shares: Vec>, + #[serde_as(as = "ferveo_common::serialization::SerdeAs")] + // pub shares: Vec>, // TODO: Using a custom type instead of referring to E:G2Affine breaks the serialization + pub shares: Vec, /// Proof of Knowledge + #[serde_as(as = "ferveo_common::serialization::SerdeAs")] pub sigma: E::G2Affine, /// Marker struct to distinguish between aggregated and @@ -85,18 +92,18 @@ pub struct PubliclyVerifiableSS { phantom: PhantomData, } -impl PubliclyVerifiableSS { +impl PubliclyVerifiableSS { /// Create a new PVSS instance /// `s`: the secret constant coefficient to share /// `dkg`: the current DKG session /// `rng` a cryptographic random number generator pub fn new( - s: &E::Fr, + s: &E::ScalarField, dkg: &PubliclyVerifiableDkg, rng: &mut R, ) -> Result { // Our random polynomial, \phi(x) = s + \sum_{i=1}^{t-1} a_i x^i - let mut phi = DensePolynomial::::rand( + let mut phi = DensePolynomial::::rand( (dkg.params.security_threshold - 1) as usize, rng, ); @@ -114,7 +121,7 @@ impl PubliclyVerifiableSS { fast_multiexp( // &evals.evals[i..i] = &evals.evals[i] &[evals.evals[val.share_index]], // one share per validator - val.validator.public_key.encryption_key.into_projective(), + val.validator.public_key.encryption_key.into_group(), )[0] }) .collect::>>(); @@ -126,7 +133,7 @@ impl PubliclyVerifiableSS { // phi.zeroize(); // TODO zeroize? // TODO: Cross check proof of knowledge check with the whitepaper; this check proves that there is a relationship between the secret and the pvss transcript // Sigma is a proof of knowledge of the secret, sigma = h^s - let sigma = E::G2Affine::prime_subgroup_generator().mul(*s).into(); //todo hash to curve + let sigma = E::G2Affine::generator().mul(*s).into(); //todo hash to curve let vss = Self { coeffs, shares, @@ -143,11 +150,11 @@ impl PubliclyVerifiableSS { // We're only checking the proof of knowledge here, sigma ?= h^s // "Does the first coefficient of the secret polynomial match the proof of knowledge?" E::pairing( - self.coeffs[0].into_projective(), // F_0 = g^s - E::G2Affine::prime_subgroup_generator(), // h + self.coeffs[0].into_group(), // F_0 = g^s + E::G2Affine::generator(), // h ) == E::pairing( - E::G1Affine::prime_subgroup_generator(), // g - self.sigma, // h^s + E::G1Affine::generator(), // g + self.sigma, // h^s ) } @@ -160,7 +167,7 @@ impl PubliclyVerifiableSS { /// function may also be used for that purpose. pub fn verify_full(&self, dkg: &PubliclyVerifiableDkg) -> bool { // compute the commitment - let mut commitment = batch_to_projective(&self.coeffs); + let mut commitment = batch_to_projective_g1::(&self.coeffs); print_time!("commitment fft"); dkg.domain.fft_in_place(&mut commitment); @@ -173,12 +180,9 @@ impl PubliclyVerifiableSS { // See #3 in 4.2.3 section of https://eprint.iacr.org/2022/898.pdf // Validator checks checks aggregated shares against commitment - let ek_i = validator - .validator - .public_key - .encryption_key - .into_projective(); - let a_i = commitment[validator.share_index]; + let ek_i = + validator.validator.public_key.encryption_key.into_group(); + let a_i = &commitment[validator.share_index]; // We verify that e(G, Y_i) = e(A_i, ek_i) for validator i // See #4 in 4.2.3 section of https://eprint.iacr.org/2022/898.pdf // e(G,Y) = e(A, ek) @@ -188,7 +192,7 @@ impl PubliclyVerifiableSS { } /// Extra methods available to aggregated PVSS transcripts -impl PubliclyVerifiableSS { +impl PubliclyVerifiableSS { /// Verify that this PVSS instance is a valid aggregation of /// the PVSS instances, produced by [`aggregate`], /// and received by the DKG context `dkg` @@ -201,11 +205,11 @@ impl PubliclyVerifiableSS { self.verify_full(dkg); // Now, we verify that the aggregated PVSS transcript is a valid aggregation // If it is, we return the total weights of the PVSS transcripts - let mut y = E::G1Projective::zero(); + let mut y = E::G1::zero(); // TODO: If we don't deal with share weights anymore, do we even need to call `verify_aggregation`? let mut shares_total = 0u32; for (_, pvss) in dkg.vss.iter() { - y += pvss.coeffs[0].into_projective(); + y += pvss.coeffs[0].into_group(); shares_total += 1 } if y.into_affine() == self.coeffs[0] { @@ -219,7 +223,7 @@ impl PubliclyVerifiableSS { pub fn decrypt_private_key_share( &self, - validator_decryption_key: &E::Fr, + validator_decryption_key: &E::ScalarField, validator_index: usize, ) -> PrivateKeyShare { // Decrypt private key shares https://nikkolasg.github.io/ferveo/pvss.html#validator-decryption-of-private-key-shares @@ -227,7 +231,7 @@ impl PubliclyVerifiableSS { .shares .get(validator_index) .unwrap() - .mul(validator_decryption_key.inverse().unwrap().into_repr()) + .mul(validator_decryption_key.inverse().unwrap()) .into_affine(); PrivateKeyShare { private_key_share } } @@ -236,7 +240,7 @@ impl PubliclyVerifiableSS { &self, ciphertext: &Ciphertext, aad: &[u8], - validator_decryption_key: &E::Fr, + validator_decryption_key: &E::ScalarField, validator_index: usize, g_inv: &E::G1Prepared, ) -> DecryptionShareSimple { @@ -259,9 +263,9 @@ impl PubliclyVerifiableSS { &self, ciphertext: &Ciphertext, aad: &[u8], - validator_decryption_key: &E::Fr, + validator_decryption_key: &E::ScalarField, validator_index: usize, - domain_points: &[E::Fr], + domain_points: &[E::ScalarField], g_inv: &E::G1Prepared, ) -> DecryptionShareSimplePrecomputed { let private_key_share = self.decrypt_private_key_share( @@ -287,9 +291,9 @@ impl PubliclyVerifiableSS { &self, ciphertext: &Ciphertext, aad: &[u8], - validator_decryption_key: &E::Fr, + validator_decryption_key: &E::ScalarField, validator_index: usize, - polynomial: &DensePolynomial, + polynomial: &DensePolynomial, dkg: &PubliclyVerifiableDkg, ) -> DecryptionShareSimple { let validator_private_key_share = self.decrypt_private_key_share( @@ -317,9 +321,9 @@ impl PubliclyVerifiableSS { pub fn update_private_key_share_for_recovery( &self, - validator_decryption_key: &E::Fr, + validator_decryption_key: &E::ScalarField, validator_index: usize, - share_updates: &[E::G2Projective], + share_updates: &[E::G2], ) -> PrivateKeyShare { // Retrieves their private key share let private_key_share = self.decrypt_private_key_share( @@ -335,42 +339,42 @@ impl PubliclyVerifiableSS { /// Aggregate the PVSS instances in `pvss` from DKG session `dkg` /// into a new PVSS instance /// See: https://nikkolasg.github.io/ferveo/pvss.html?highlight=aggregate#aggregation -pub fn aggregate( +pub fn aggregate( dkg: &PubliclyVerifiableDkg, ) -> PubliclyVerifiableSS { let pvss = &dkg.vss; let mut pvss_iter = pvss.iter(); let (_, first_pvss) = pvss_iter.next().unwrap(); - let mut coeffs = batch_to_projective(&first_pvss.coeffs); + let mut coeffs = batch_to_projective_g1::(&first_pvss.coeffs); let mut sigma = first_pvss.sigma; - let mut shares = batch_to_projective(&first_pvss.shares); + let mut shares = batch_to_projective_g2::(&first_pvss.shares); // So now we're iterating over the PVSS instances, and adding their coefficients and shares, and their sigma // sigma is the sum of all the sigma_i, which is the proof of knowledge of the secret polynomial // Aggregating is just adding the corresponding values in pvss instances, so pvss = pvss + pvss_j for (_, next) in pvss_iter { - sigma = sigma.add(next.sigma); + sigma = (sigma + next.sigma).into(); coeffs .iter_mut() .zip_eq(next.coeffs.iter()) - .for_each(|(a, b)| *a += b.into_projective()); + .for_each(|(a, b)| *a += b); shares .iter_mut() .zip_eq(next.shares.iter()) - .for_each(|(a, b)| *a += b.into_projective()); + .for_each(|(a, b)| *a += b); } - let shares = E::G2Projective::batch_normalization_into_affine(&shares); + let shares = E::G2::normalize_batch(&shares); PubliclyVerifiableSS { - coeffs: E::G1Projective::batch_normalization_into_affine(&coeffs), + coeffs: E::G1::normalize_batch(&coeffs), shares, sigma, phantom: Default::default(), } } -pub fn aggregate_for_decryption( +pub fn aggregate_for_decryption( dkg: &PubliclyVerifiableDkg, ) -> Vec> { // From docs: https://nikkolasg.github.io/ferveo/pvss.html?highlight=aggregate#aggregation @@ -388,12 +392,12 @@ pub fn aggregate_for_decryption( .fold(first_share, |acc, shares| { acc.into_iter() .zip_eq(shares.into_iter()) - .map(|(a, b)| a + b) + .map(|(a, b)| (a + b).into()) .collect() }) } -pub fn make_decryption_shares( +pub fn make_decryption_shares( ciphertext: &Ciphertext, validator_keypairs: &[Keypair], aggregate: &[E::G2Affine], @@ -407,8 +411,8 @@ pub fn make_decryption_shares( .enumerate() .map(|(decrypter_index, (encrypted_share, keypair))| { // Decrypt private key shares https://nikkolasg.github.io/ferveo/pvss.html#validator-decryption-of-private-key-shares - let z_i = encrypted_share - .mul(keypair.decryption_key.inverse().unwrap().into_repr()); + let z_i = + encrypted_share.mul(keypair.decryption_key.inverse().unwrap()); // TODO: Consider using "container" structs from `tpke` for other primitives let private_key_share = PrivateKeyShare { private_key_share: z_i.into_affine(), @@ -430,15 +434,16 @@ pub fn make_decryption_shares( #[cfg(test)] mod test_pvss { use ark_bls12_381::Bls12_381 as EllipticCurve; + use ark_ec::AffineRepr; use ark_ff::UniformRand; use ferveo_common::ExternalValidator; use super::*; use crate::dkg::pv::test_common::*; - type Fr = ::Fr; - type G1 = ::G1Affine; - type G2 = ::G2Affine; + type ScalarField = ::ScalarField; + type G1 = ::G1Affine; + type G2 = ::G2Affine; /// Test the happy flow that a pvss with the correct form is created /// and that appropriate validations pass @@ -446,17 +451,17 @@ mod test_pvss { fn test_new_pvss() { let rng = &mut ark_std::test_rng(); let dkg = setup_dkg(0); - let s = Fr::rand(rng); + let s = ScalarField::rand(rng); let pvss = Pvss::::new(&s, &dkg, rng).expect("Test failed"); // check that the chosen secret coefficient is correct - assert_eq!(pvss.coeffs[0], G1::prime_subgroup_generator().mul(s)); + assert_eq!(pvss.coeffs[0], G1::generator().mul(s)); //check that a polynomial of the correct degree was created assert_eq!(pvss.coeffs.len(), dkg.params.security_threshold as usize); // check that the correct number of shares were created assert_eq!(pvss.shares.len(), dkg.validators.len()); // check that the prove of knowledge is correct - assert_eq!(pvss.sigma, G2::prime_subgroup_generator().mul(s)); + assert_eq!(pvss.sigma, G2::generator().mul(s)); // check that the optimistic verify returns true assert!(pvss.verify_optimistic()); // check that the full verify returns true @@ -469,10 +474,10 @@ mod test_pvss { fn test_verify_pvss_wrong_proof_of_knowledge() { let rng = &mut ark_std::test_rng(); let dkg = setup_dkg(0); - let mut s = Fr::rand(rng); + let mut s = ScalarField::rand(rng); // ensure that the proof of knowledge is not zero - while s == Fr::zero() { - s = Fr::rand(rng); + while s == ScalarField::zero() { + s = ScalarField::rand(rng); } let mut pvss = PubliclyVerifiableSS::::new(&s, &dkg, rng) @@ -487,7 +492,7 @@ mod test_pvss { fn test_verify_pvss_bad_shares() { let rng = &mut ark_std::test_rng(); let dkg = setup_dkg(0); - let s = Fr::rand(rng); + let s = ScalarField::rand(rng); let pvss = Pvss::::new(&s, &dkg, rng).unwrap(); // So far, everything works diff --git a/subproductdomain/Cargo.toml b/subproductdomain/Cargo.toml index 99b593cd..6de84da8 100644 --- a/subproductdomain/Cargo.toml +++ b/subproductdomain/Cargo.toml @@ -7,14 +7,14 @@ authors = ["Heliax AG "] [dependencies] anyhow = "1.0.47" -ark-std = "0.3" -ark-ec = "0.3" -ark-ff = "0.3" -ark-serialize = "0.3" -ark-poly = "0.3" +ark-std = "0.4" +ark-ec = "0.4" +ark-ff = "0.4" +ark-serialize = "0.4" +ark-poly = "0.4" [dev-dependencies] -ark-bls12-381 = "0.3" +ark-bls12-381 = "0.4" [profile.release] opt-level = 3 diff --git a/subproductdomain/src/lib.rs b/subproductdomain/src/lib.rs index 82977361..e3538312 100644 --- a/subproductdomain/src/lib.rs +++ b/subproductdomain/src/lib.rs @@ -1,41 +1,43 @@ #![allow(non_snake_case)] #![allow(dead_code)] -use ark_ec::{msm::FixedBaseMSM, PairingEngine, ProjectiveCurve}; -use ark_ff::{FftField, Field, PrimeField, Zero}; -use ark_poly::polynomial::univariate::DensePolynomial as Poly; -use ark_poly::{Polynomial, UVPolynomial}; +use ark_ec::pairing::Pairing; +use ark_ec::scalar_mul::fixed_base::FixedBase; +use ark_ec::AffineRepr; +use ark_ec::CurveGroup; +use ark_ff::{FftField, Field, Zero}; +use ark_poly::univariate::DensePolynomial; +use ark_poly::DenseUVPolynomial; +use ark_poly::EvaluationDomain; +use ark_poly::{Polynomial, Radix2EvaluationDomain}; /// Compute a fast multiexp of many scalars times the same base /// Only convenient for when called once with given base; if called /// more than once, it's faster to save the generated window table -pub fn fast_multiexp( - scalars: &[Projective::ScalarField], - base: Projective, -) -> Vec { - let window_size = FixedBaseMSM::get_mul_window_size(scalars.len()); - - let scalar_bits = Projective::ScalarField::size_in_bits(); +pub fn fast_multiexp( + scalars: &[Group::ScalarField], + base: Group, +) -> Vec { + let window_size = FixedBase::get_mul_window_size(scalars.len()); + + // let scalar_bits = mem::size_of::(); + let scalar_bits: usize = 255; // TODO: How to get this from the scalar field? let base_table = - FixedBaseMSM::get_window_table(scalar_bits, window_size, base); - - let exp = FixedBaseMSM::multi_scalar_mul::( - scalar_bits, - window_size, - &base_table, - scalars, - ); - Projective::batch_normalization_into_affine(&exp) + FixedBase::get_window_table(scalar_bits, window_size, base); + + let exp = + FixedBase::msm::(scalar_bits, window_size, &base_table, scalars); + Group::normalize_batch(&exp) } #[allow(dead_code)] -pub fn poly_from_scalar(s: &F) -> Poly { - Poly:: { coeffs: vec![*s] } +pub fn poly_from_scalar(s: &F) -> DensePolynomial { + DensePolynomial:: { coeffs: vec![*s] } } #[allow(dead_code)] -pub fn moduli_from_scalar(s: &F) -> Poly { - Poly:: { +pub fn moduli_from_scalar(s: &F) -> DensePolynomial { + DensePolynomial:: { coeffs: vec![-*s, F::one()], } } @@ -48,13 +50,13 @@ pub fn moduli_from_scalar(s: &F) -> Poly { /// Computes the inverse of f mod x^l /// Takes O(M(l)) field arithmetic operations pub fn inverse_mod_xl( - func: &Poly, + func: &DensePolynomial, length: usize, -) -> Option> { +) -> Option> { let log = ark_std::log2(length); // Compute ceil(log_2(l)) if let Some(f_0_inv) = func.coeffs[0].inverse() { // Invert f(0)^-1 if possible - let mut func_inv = Poly:: { + let mut func_inv = DensePolynomial:: { coeffs: vec![f_0_inv], // Constant polynomial f(0)^-1 }; @@ -79,7 +81,7 @@ pub fn inverse_mod_xl( /// GG chapter 9.1 /// Computes the rev_m(f) function in place /// rev_m(f) = x^m f(1/x) -pub fn rev(f: &mut Poly, m: usize) { +pub fn rev(f: &mut DensePolynomial, m: usize) { assert!(f.coeffs.len() - 1 <= m); for _ in 0..(m - (f.coeffs.len() - 1)) { f.coeffs.push(F::zero()); @@ -90,14 +92,14 @@ pub fn rev(f: &mut Poly, m: usize) { /// GG Algorithm 9.5 /// Divide f by g in nearly linear time pub fn fast_divide_monic( - func: &Poly, - divisor: &Poly, -) -> (Poly, Poly) { + func: &DensePolynomial, + divisor: &DensePolynomial, +) -> (DensePolynomial, DensePolynomial) { //TODO: check monic condition if func.coeffs().len() < divisor.coeffs().len() { return ( - Poly:: { + DensePolynomial:: { coeffs: vec![F::zero()], }, func.clone(), @@ -133,7 +135,7 @@ pub struct SubproductDomain { /// Subproduct tree over domain u pub t: SubproductTree, /// Derivative of the subproduct polynomial - pub prime: Poly, // Derivative of the polynomial m + pub prime: DensePolynomial, // Derivative of the polynomial m } impl SubproductDomain { @@ -146,7 +148,7 @@ impl SubproductDomain { #[allow(dead_code)] /// Evaluate a polynomial f over the subproduct domain u - pub fn evaluate(&self, f: &Poly) -> Vec { + pub fn evaluate(&self, f: &DensePolynomial) -> Vec { let mut evals = vec![F::zero(); self.u.len()]; self.t.evaluate(f, &self.u, &mut evals); evals @@ -154,7 +156,7 @@ impl SubproductDomain { #[allow(dead_code)] /// Interpolate a polynomial f over the domain, such that f(u_i) = v_i - pub fn interpolate(&self, v: &[F]) -> Poly { + pub fn interpolate(&self, v: &[F]) -> DensePolynomial { self.t.interpolate(&self.u, v) } @@ -165,7 +167,7 @@ impl SubproductDomain { #[allow(dead_code)] /// Compute a linear combination of lagrange factors times c_i - pub fn linear_combine(&self, c: &[F]) -> Poly { + pub fn linear_combine(&self, c: &[F]) -> DensePolynomial { self.t.linear_combine(&self.u, c) } } @@ -182,7 +184,7 @@ pub struct SubproductTree { /// The right child SubproductTree pub right: Option>>, /// The polynomial m = (x - u_i)*...*(x-u_j) for this subdomain - pub m: Poly, + pub m: DensePolynomial, } impl SubproductTree { @@ -197,7 +199,7 @@ impl SubproductTree { SubproductTree { left: None, right: None, - m: Poly:: { + m: DensePolynomial:: { coeffs: vec![-u[0], F::one()], // m_0 = x - u_0 }, } @@ -222,7 +224,7 @@ impl SubproductTree { /// The output is stored in the slice t: /// t_i = f(u_i) /// Takes O(M(n) log n) field operations - pub fn evaluate(&self, f: &Poly, u: &[F], t: &mut [F]) { + pub fn evaluate(&self, f: &DensePolynomial, u: &[F], t: &mut [F]) { assert!(f.degree() < u.len()); if u.len() == 1 { @@ -250,7 +252,7 @@ impl SubproductTree { #[allow(dead_code)] /// Fast interpolate over this subproduct tree - pub fn interpolate(&self, u: &[F], v: &[F]) -> Poly { + pub fn interpolate(&self, u: &[F], v: &[F]) -> DensePolynomial { let mut lagrange_coeff = self.inverse_lagrange_coefficients(u); for (s_i, v_i) in lagrange_coeff.iter_mut().zip(v.iter()) { @@ -278,10 +280,10 @@ impl SubproductTree { /// On input c = { c_0, ..., c_{n-1} } /// output sum_i (c_i * m) / (x- u_i) /// Takes O(M(n) log n) field operations - pub fn linear_combine(&self, u: &[F], c: &[F]) -> Poly { + pub fn linear_combine(&self, u: &[F], c: &[F]) -> DensePolynomial { if u.len() == 1 { // Output c_0 * (x-u_0) / (x-u_0) = c_0 - return Poly:: { coeffs: vec![c[0]] }; + return DensePolynomial:: { coeffs: vec![c[0]] }; } let n = u.len() / 2; let (u_0, u_1) = u.split_at(n); @@ -300,19 +302,19 @@ impl SubproductTree { } /// Compute the derivative of polynomial f -pub fn derivative(f: &Poly) -> Poly { +pub fn derivative(f: &DensePolynomial) -> DensePolynomial { let mut coeffs = Vec::with_capacity(f.coeffs().len() - 1); for (i, c) in f.coeffs.iter().enumerate().skip(1) { coeffs.push(F::from(i as u128) * c); } - Poly:: { coeffs } + DensePolynomial:: { coeffs } } /// Build a vector representation of the (n x n) circulant matrix of polynomial f /// Based on the blog post: /// https://alinush.github.io/2020/03/19/multiplying-a-vector-by-a-toeplitz-matrix.html pub fn build_circulant( - f: &Poly, + f: &DensePolynomial, n: usize, // Build a 2n x 2n circulant matrix ) -> Vec { assert!(n >= f.degree()); @@ -332,36 +334,35 @@ pub fn build_circulant( #[allow(dead_code)] /// Computes the Toeplitz matrix of polynomial times the vector v -pub fn toeplitz_mul( - polynomial: &Poly, +pub fn toeplitz_mul( + polynomial: &DensePolynomial, v: &[E::G1Affine], size: usize, -) -> Result<(Vec, E::Fr), anyhow::Error> { - use ark_ec::AffineCurve; - use ark_poly::EvaluationDomain; - let m = polynomial.coeffs().len() - 1; +) -> Result<(Vec, E::ScalarField), anyhow::Error> { + let m = polynomial.coeffs.len() - 1; let size = ark_std::cmp::max(size, m); - let domain = ark_poly::Radix2EvaluationDomain::::new(2 * size) + let domain = Radix2EvaluationDomain::::new(2 * size) .ok_or_else(|| { anyhow::anyhow!("toeplitz multiplication on too large a domain") })?; let circulant_size = domain.size(); let toeplitz_size = circulant_size / 2; - let mut circulant = build_circulant::(polynomial, toeplitz_size); + let mut circulant = + build_circulant::(polynomial, toeplitz_size); - let mut tmp: Vec = Vec::with_capacity(circulant_size); + let mut tmp: Vec = Vec::with_capacity(circulant_size); for _ in 0..(toeplitz_size - v.len()) { - tmp.push(E::G1Projective::zero()); + tmp.push(E::G1::zero()); } for i in v.iter().rev() { - tmp.push(i.into_projective()); + tmp.push(i.into_group()); } - tmp.resize(circulant_size, E::G1Projective::zero()); + tmp.resize(circulant_size, E::G1::zero()); domain.fft_in_place(&mut tmp); domain.fft_in_place(&mut circulant); @@ -374,22 +375,23 @@ pub fn toeplitz_mul( Ok(( tmp[..toeplitz_size].to_vec(), - E::Fr::from(domain.size() as u128).inverse().unwrap(), + E::ScalarField::from(domain.size() as u128) + .inverse() + .unwrap(), )) } #[cfg(test)] mod tests { - use ark_ec::PairingEngine; + use ark_ec::pairing::Pairing; use ark_ff::{One, Zero}; use ark_poly::polynomial::univariate::DensePolynomial; use ark_poly::Polynomial; - use ark_poly::UVPolynomial; use ark_std::UniformRand; use super::*; - type Fr = ::Fr; + type ScalarField = ::ScalarField; #[test] fn test_inverse() { let rng = &mut ark_std::test_rng(); @@ -397,13 +399,13 @@ mod tests { for l in [1, 2, 3, 5, 19, 25, 101].iter() { for degree in 0..(l + 4) { for _ in 0..10 { - let p = DensePolynomial::::rand(degree, rng); - let p_inv = inverse_mod_xl::(&p, *l).unwrap(); + let p = DensePolynomial::::rand(degree, rng); + let p_inv = inverse_mod_xl::(&p, *l).unwrap(); let mut t = &p * &p_inv; // p * p^-1 - t.coeffs.resize(*l, Fr::zero()); // mod x^l - assert_eq!(t.coeffs[0], Fr::one()); // constant term == 1 + t.coeffs.resize(*l, ScalarField::zero()); // mod x^l + assert_eq!(t.coeffs[0], ScalarField::one()); // constant term == 1 for i in t.iter().skip(1) { - assert_eq!(*i, Fr::zero()); // all other terms == 0 + assert_eq!(*i, ScalarField::zero()); // all other terms == 0 } } } @@ -416,11 +418,11 @@ mod tests { let degree = 100; for g_deg in 1..100 { - let f = DensePolynomial::::rand(degree, rng); - let mut g = DensePolynomial::::rand(g_deg, rng); - *g.last_mut().unwrap() = Fr::one(); //monic + let f = DensePolynomial::::rand(degree, rng); + let mut g = DensePolynomial::::rand(g_deg, rng); + *g.last_mut().unwrap() = ScalarField::one(); //monic - let (q, r) = fast_divide_monic::(&f, &g); + let (q, r) = fast_divide_monic::(&f, &g); let t = &(&q * &g) + &r; @@ -437,11 +439,11 @@ mod tests { let mut points = vec![]; let mut evals = vec![]; for _ in 0..d { - points.push(Fr::rand(rng)); - evals.push(Fr::rand(rng)); + points.push(ScalarField::rand(rng)); + evals.push(ScalarField::rand(rng)); } - let s = SubproductDomain::::new(points); + let s = SubproductDomain::::new(points); let p = s.interpolate(&evals); for (x, y) in s.u.iter().zip(evals.iter()) { @@ -457,15 +459,15 @@ mod tests { let mut u = vec![]; let mut c = vec![]; for _ in 0..d { - u.push(Fr::rand(rng)); - c.push(Fr::rand(rng)); + u.push(ScalarField::rand(rng)); + c.push(ScalarField::rand(rng)); } - let s = SubproductDomain::::new(u); + let s = SubproductDomain::::new(u); let f = s.linear_combine(&c); - let r = Fr::rand(rng); + let r = ScalarField::rand(rng); let m = s.t.m.evaluate(&r); - let mut total = Fr::zero(); + let mut total = ScalarField::zero(); for (u_i, c_i) in s.u.iter().zip(c.iter()) { total += m * *c_i / (r - u_i); } @@ -479,9 +481,9 @@ mod tests { for d in 1..100 { let mut u = vec![]; for _ in 0..d { - u.push(Fr::rand(rng)); + u.push(ScalarField::rand(rng)); } - let s = SubproductDomain::::new(u); + let s = SubproductDomain::::new(u); let f = s.inverse_lagrange_coefficients(); for (i, j) in s.u.iter().zip(f.iter()) { diff --git a/tpke-wasm/Cargo.toml b/tpke-wasm/Cargo.toml index 5a211296..6f65f389 100644 --- a/tpke-wasm/Cargo.toml +++ b/tpke-wasm/Cargo.toml @@ -16,19 +16,20 @@ test-common = ["group-threshold-cryptography/test-common"] [dependencies] group-threshold-cryptography = { path = "../tpke", features = ["test-common"] } +ferveo-common = { path = "../ferveo-common" } wasm-bindgen = { version = "0.2.74", features = ["serde-serialize"] } console_error_panic_hook = { version = "0.1.7", optional = true } wee_alloc = { version = "0.4.5" } getrandom = { version = "0.2", features = ["js"] } rand = "0.8.5" -ark-bls12-381 = "0.3.0" -ark-ff = "0.3.0" +ark-bls12-381 = "0.4" +ark-ff = "0.4" bincode = "1.3.3" serde = { version = "1.0", features = ["derive"] } serde_with = "2.0.1" -ark-serialize = { version = "0.3", features = ["derive"] } -ark-ec = "0.3" -ark-std = "0.3.0" +ark-serialize = { version = "0.4", features = ["derive"] } +ark-ec = "0.4" +ark-std = "0.4" rand_core = "0.6" [dev-dependencies] diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index 9acd3caa..715cbe18 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -56,7 +56,7 @@ impl DecryptionShareSimplePrecomputed { #[wasm_bindgen] #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct PublicKey( - #[serde_as(as = "tpke::serialization::SerdeAs")] + #[serde_as(as = "ferveo_common::serialization::SerdeAs")] pub(crate) tpke::api::TpkeDkgPublicKey, ); @@ -83,7 +83,7 @@ impl PublicKey { #[wasm_bindgen] #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct PrivateKey( - #[serde_as(as = "tpke::serialization::SerdeAs")] + #[serde_as(as = "ferveo_common::serialization::SerdeAs")] pub(crate) tpke::api::TpkePrivateKey, ); diff --git a/tpke/Cargo.toml b/tpke/Cargo.toml index 92cd51f9..2cd45cd6 100644 --- a/tpke/Cargo.toml +++ b/tpke/Cargo.toml @@ -17,20 +17,18 @@ test-common = [] [dependencies] subproductdomain = { path = "../subproductdomain" } ferveo-common = { path = "../ferveo-common" } -hex = "=0.4.3" rand_core = "0.6" rand = "0.8" -rayon = "1.5" thiserror = "=1.0.30" anyhow = "=1.0" rust-crypto = "0.2.36" miracl_core = "=2.3.0" -ark-ff = "0.3" -ark-ec = "0.3" -ark-poly = "0.3" -ark-serialize = "0.3" -ark-std = "0.3" -ark-bls12-381 = "0.3" +ark-ff = "0.4" +ark-ec = "0.4" +ark-poly = "0.4" +ark-serialize = "0.4" +ark-std = "0.4" +ark-bls12-381 = "0.4" itertools = "0.10" chacha20poly1305 = "0.10.1" serde = { version = "1.0", features = ["derive"] } @@ -39,6 +37,7 @@ bincode = "1.3.3" [dev-dependencies] criterion = { version = "0.4", features = ["html_reports"] } +hex = "=0.4.3" [[bench]] name = "tpke" diff --git a/tpke/benches/arkworks.rs b/tpke/benches/arkworks.rs index 3247c995..3abe9689 100644 --- a/tpke/benches/arkworks.rs +++ b/tpke/benches/arkworks.rs @@ -1,10 +1,13 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::unit_arg)] -use ark_bls12_381::{Bls12_381, Fr}; -use ark_ec::{ - prepare_g1, prepare_g2, AffineCurve, PairingEngine, ProjectiveCurve, +use std::ops::Mul; + +use ark_bls12_381::{ + Bls12_381, Fr, G1Affine, G1Projective, G2Affine, G2Projective, }; +use ark_ec::pairing::{prepare_g1, prepare_g2, Pairing}; +use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::{BigInteger256, Field, One, UniformRand, Zero}; use criterion::{black_box, criterion_group, BenchmarkId, Criterion}; use group_threshold_cryptography::make_random_polynomial_at; @@ -13,13 +16,9 @@ use rand::prelude::StdRng; use rand_core::{RngCore, SeedableRng}; type E = Bls12_381; -type G1Projective = ark_ec::bls12::G1Projective; -type G1Affine = ark_ec::bls12::G1Affine; -type G1Prepared = ::G1Prepared; -type G2Projective = ark_ec::bls12::G2Projective; -type G2Affine = ark_ec::bls12::G2Affine; -type G2Prepared = ::G2Prepared; -type Fqk = ::Fqk; +type G1Prepared = ::G1Prepared; +type G2Prepared = ::G2Prepared; +type TargetField = ::TargetField; const BENCH_CASES: [usize; 7] = [1, 2, 4, 8, 16, 32, 64]; @@ -32,12 +31,12 @@ pub fn bench_mul(c: &mut Criterion) { let g2 = G2Projective::rand(&mut rng); let g1_affine = g1.into_affine(); let g2_affine = g2.into_affine(); - let int = BigInteger256::rand(&mut rng); + let r = Fr::rand(&mut rng); - group.bench_function("G1Projective", |b| b.iter(|| g1.mul(int))); - group.bench_function("G2Projective", |b| b.iter(|| g2.mul(int))); - group.bench_function("G1Affine", |b| b.iter(|| g1_affine.mul(int))); - group.bench_function("G2Affine", |b| b.iter(|| g2_affine.mul(int))); + group.bench_function("G1", |b| b.iter(|| g1.mul(r))); + group.bench_function("G2Projective", |b| b.iter(|| g2.mul(r))); + group.bench_function("G1Affine", |b| b.iter(|| g1_affine.mul(r))); + group.bench_function("G2Affine", |b| b.iter(|| g2_affine.mul(r))); } pub fn bench_into_affine(c: &mut Criterion) { @@ -48,22 +47,20 @@ pub fn bench_into_affine(c: &mut Criterion) { let g1 = G1Projective::rand(&mut rng); let g2 = G2Projective::rand(&mut rng); - group.bench_function("G1Projective", |b| b.iter(|| g1.into_affine())); + group.bench_function("G1", |b| b.iter(|| g1.into_affine())); group.bench_function("G2Projective", |b| b.iter(|| g2.into_affine())); } pub fn bench_into_projective(c: &mut Criterion) { let mut rng = &mut StdRng::seed_from_u64(0); - let mut group = c.benchmark_group("into_projective"); + let mut group = c.benchmark_group("into_group"); let g1_affine = G1Projective::rand(&mut rng).into_affine(); let g2_affine = G2Projective::rand(&mut rng).into_affine(); - group - .bench_function("G1Affine", |b| b.iter(|| g1_affine.into_projective())); - group - .bench_function("G2Affine", |b| b.iter(|| g2_affine.into_projective())); + group.bench_function("G1Affine", |b| b.iter(|| g1_affine.into_group())); + group.bench_function("G2Affine", |b| b.iter(|| g2_affine.into_group())); } pub fn bench_prepare_gx(c: &mut Criterion) { @@ -83,23 +80,26 @@ pub fn bench_pow(c: &mut Criterion) { let mut group = c.benchmark_group("pow"); - let fqk = Fqk::rand(&mut rng); + let fqk = TargetField::rand(&mut rng); let int = BigInteger256::rand(&mut rng); - group.bench_function("Fqk", |b| b.iter(|| fqk.pow(int))); + group.bench_function("TargetField", |b| b.iter(|| fqk.pow(int))); } fn make_prepared_pairing_inputs( size: usize, rng: &mut StdRng, -) -> Vec<(G1Prepared, G2Prepared)> { +) -> (Vec, Vec) { let (p, q) = make_pairing_inputs(size, rng); - let pq = &p - .iter() - .zip(q.iter()) - .map(|(i, j)| (G1Prepared::from(*i), G2Prepared::from(*j))) - .collect::>(); - pq.to_vec() + let p = p + .into_iter() + .map(|i| G1Prepared::from(i)) + .collect::>(); + let q = q + .into_iter() + .map(|i| G2Prepared::from(i)) + .collect::>(); + (p, q) } fn make_pairing_inputs( @@ -107,18 +107,10 @@ fn make_pairing_inputs( rng: &mut StdRng, ) -> (Vec, Vec) { let p = (0..size) - .map(|_| { - G1Affine::prime_subgroup_generator() - .mul(Fr::rand(rng)) - .into_affine() - }) + .map(|_| G1Affine::generator().mul(Fr::rand(rng)).into_affine()) .collect::>(); let q = (0..size) - .map(|_| { - G2Affine::prime_subgroup_generator() - .mul(Fr::rand(rng)) - .into_affine() - }) + .map(|_| G2Affine::generator().mul(Fr::rand(rng)).into_affine()) .collect::>(); (p, q) } @@ -128,13 +120,15 @@ pub fn bench_miller_loop(c: &mut Criterion) { let mut group = c.benchmark_group("miller_loop"); - let pq = + let (p, q) = make_prepared_pairing_inputs(BENCH_CASES[BENCH_CASES.len() - 1], rng); for nr_of_inputs in BENCH_CASES { + let p = p.iter().take(nr_of_inputs).cloned().collect::>(); + let q = q.iter().take(nr_of_inputs).cloned().collect::>(); group.bench_function( BenchmarkId::new("BLS12-381 miller_loop", nr_of_inputs), - |b| b.iter(|| E::miller_loop(pq.iter().take(nr_of_inputs))), + |b| b.iter(|| E::multi_miller_loop(p.clone(), q.clone())), ); } } @@ -144,20 +138,22 @@ pub fn bench_final_exponentiation(c: &mut Criterion) { let mut group = c.benchmark_group("final_exponentiation"); - let pq = + let (p, q) = make_prepared_pairing_inputs(BENCH_CASES[BENCH_CASES.len() - 1], rng); + let ml = BENCH_CASES .iter() .map(|nr_of_inputs| { - let pq = pq.iter().take(*nr_of_inputs).collect::>(); - E::miller_loop(pq) + let p = p.iter().take(*nr_of_inputs).cloned().collect::>(); + let q = q.iter().take(*nr_of_inputs).cloned().collect::>(); + E::multi_miller_loop(p, q) }) .collect::>(); for (ml, nr_of_inputs) in izip!(ml, BENCH_CASES) { group.bench_function( BenchmarkId::new("BLS12-381 final_exponentiation", nr_of_inputs), - |b| b.iter(|| E::final_exponentiation(&ml)), + |b| b.iter(|| E::final_exponentiation(ml)), ); } } @@ -177,20 +173,28 @@ pub fn bench_pairing(c: &mut Criterion) { pub fn bench_product_of_pairings(c: &mut Criterion) { let rng = &mut StdRng::seed_from_u64(0); - let mut group = c.benchmark_group("product_of_pairings"); + let mut group = c.benchmark_group("multi_pairing"); group.sample_size(10); - let pq = + let (p, q) = make_prepared_pairing_inputs(BENCH_CASES[BENCH_CASES.len() - 1], rng); for nr_of_inputs in BENCH_CASES { group.bench_function( - BenchmarkId::new("BLS12-381 product_of_pairings", nr_of_inputs), + BenchmarkId::new("BLS12-381 multi_pairing", nr_of_inputs), |b| { b.iter(|| { - black_box(Bls12_381::product_of_pairings( - pq.iter().take(nr_of_inputs), - )) + let p = p + .iter() + .take(nr_of_inputs) + .cloned() + .collect::>(); + let q = q + .iter() + .take(nr_of_inputs) + .cloned() + .collect::>(); + black_box(Bls12_381::multi_miller_loop(p, q)) }) }, ); @@ -201,12 +205,9 @@ pub fn bench_random_poly(c: &mut Criterion) { let mut group = c.benchmark_group("random_polynomial_evaluation"); group.sample_size(10); - fn evaluate_polynomial( - polynomial: &[E::Fr], - x: &E::Fr, - ) -> E::Fr { - let mut result = E::Fr::zero(); - let mut x_power = E::Fr::one(); + fn evaluate_polynomial(polynomial: &[Fr], x: &Fr) -> Fr { + let mut result = Fr::zero(); + let mut x_power = Fr::one(); for coeff in polynomial { result += *coeff * x_power; x_power *= x; @@ -214,26 +215,26 @@ pub fn bench_random_poly(c: &mut Criterion) { result } - pub fn naive_make_random_polynomial_at( + pub fn naive_make_random_polynomial_at( threshold: usize, - root: &E::Fr, + root: &Fr, rng: &mut impl RngCore, - ) -> Vec { + ) -> Vec { // [][threshold-1] let mut d_i = (0..threshold - 1) - .map(|_| E::Fr::rand(rng)) + .map(|_| Fr::rand(rng)) .collect::>(); // [0..][threshold] - d_i.insert(0, E::Fr::zero()); + d_i.insert(0, Fr::zero()); // Now, we calculate d_i_0 // This is the term that will "zero out" the polynomial at x_r, d_i(x_r) = 0 - let d_i_0 = E::Fr::zero() - evaluate_polynomial::(&d_i, root); + let d_i_0 = Fr::zero() - evaluate_polynomial::(&d_i, root); d_i[0] = d_i_0; - assert_eq!(evaluate_polynomial::(&d_i, root), E::Fr::zero()); + assert_eq!(evaluate_polynomial::(&d_i, root), Fr::zero()); debug_assert!(d_i.len() == threshold); - debug_assert!(evaluate_polynomial::(&d_i, root) == E::Fr::zero()); + debug_assert!(evaluate_polynomial::(&d_i, root) == Fr::zero()); d_i } diff --git a/tpke/benches/tpke.rs b/tpke/benches/tpke.rs index 537e2017..e57eb07f 100644 --- a/tpke/benches/tpke.rs +++ b/tpke/benches/tpke.rs @@ -2,8 +2,9 @@ use std::collections::HashMap; -use ark_bls12_381::{Fr, G1Affine, G2Affine}; -use ark_ec::AffineCurve; +use ark_bls12_381::{Bls12_381, Fr, G1Affine as G1, G2Affine as G2}; +use ark_ec::pairing::Pairing; +use ark_ec::AffineRepr; use ark_ff::Zero; use criterion::{ black_box, criterion_group, criterion_main, BenchmarkId, Criterion, @@ -16,9 +17,9 @@ use rand_core::{RngCore, SeedableRng}; const NUM_SHARES_CASES: [usize; 5] = [4, 8, 16, 32, 64]; const MSG_SIZE_CASES: [usize; 7] = [256, 512, 1024, 2048, 4096, 8192, 16384]; -type E = ark_bls12_381::Bls12_381; -type G2Prepared = ark_ec::bls12::G2Prepared; -type Fqk = ::Fqk; +type E = Bls12_381; +type G2Prepared = ::G2Prepared; +type TargetField = ::TargetField; #[allow(dead_code)] struct SetupShared { @@ -26,10 +27,10 @@ struct SetupShared { shares_num: usize, msg: Vec, aad: Vec, - pubkey: G1Affine, - privkey: G2Affine, + pubkey: G1, + privkey: G2, ciphertext: Ciphertext, - shared_secret: Fqk, + shared_secret: TargetField, } struct SetupFast { @@ -49,7 +50,7 @@ impl SetupFast { let (pubkey, privkey, contexts) = setup_fast::(threshold, shares_num, rng); - let ciphertext = encrypt::<_, E>(&msg, aad, &pubkey, rng); + let ciphertext = encrypt::(&msg, aad, &pubkey, rng); let mut decryption_shares: Vec> = vec![]; for context in contexts.iter() { @@ -105,7 +106,7 @@ impl SetupSimple { setup_simple::(threshold, shares_num, rng); // Ciphertext.commitment is already computed to match U - let ciphertext = encrypt::<_, E>(&msg, aad, &pubkey, rng); + let ciphertext = encrypt::(&msg, aad, &pubkey, rng); // Creating decryption shares let decryption_shares: Vec<_> = contexts @@ -335,7 +336,7 @@ pub fn bench_share_encrypt_decrypt(c: &mut Criterion) { let mut rng = rng.clone(); let setup = SetupFast::new(shares_num, msg_size, &mut rng); move || { - black_box(encrypt::<_, E>( + black_box(encrypt::( &setup.shared.msg, &setup.shared.aad, &setup.shared.pubkey, @@ -547,7 +548,7 @@ pub fn bench_refresh_shares(c: &mut Criterion) { |b| { b.iter(|| { black_box(refresh_private_key_share::( - &p.setup_params.h.into_projective(), + &p.setup_params.h.into_group(), &p.public_decryption_contexts[0].domain, &polynomial, &p.private_key_share, diff --git a/tpke/src/api.rs b/tpke/src/api.rs index 09994d35..35137cd8 100644 --- a/tpke/src/api.rs +++ b/tpke/src/api.rs @@ -4,12 +4,14 @@ // TODO: Refactor this module to deduplicate shared code from tpke-wasm and tpke-wasm. -use ark_serialize::*; +use ferveo_common::serialization; +use serde::{Deserialize, Serialize}; +use serde_with::serde_as; pub type E = ark_bls12_381::Bls12_381; pub type TpkeDkgPublicKey = ark_bls12_381::G1Affine; -pub type TpkeG1Prepared = ::G1Prepared; -pub type TpkeG1Affine = ::G1Affine; +pub type TpkeG1Prepared = ::G1Prepared; +pub type TpkeG1Affine = ::G1Affine; pub type TpkePrivateKey = ark_bls12_381::G2Affine; pub type TpkeUnblindingKey = ark_bls12_381::Fr; pub type TpkeDomainPoint = ark_bls12_381::Fr; @@ -18,7 +20,7 @@ pub type TpkeDecryptionShareSimplePrecomputed = crate::DecryptionShareSimplePrecomputed; pub type TpkeDecryptionShareSimple = crate::DecryptionShareSimple; pub type TpkePublicDecryptionContext = crate::PublicDecryptionContextSimple; -pub type TpkeSharedSecret = ::Fqk; +pub type TpkeSharedSecret = ::TargetField; pub type TpkeResult = crate::Result; pub type TpkePrivateDecryptionContext = crate::PrivateDecryptionContextSimple; @@ -51,21 +53,19 @@ pub fn decrypt_symmetric( crate::decrypt_symmetric(&ciphertext.0, aad, private_key, g_inv).unwrap() } -#[derive(Clone, Debug, PartialEq, CanonicalSerialize, CanonicalDeserialize)] -pub struct DomainPoint(pub TpkeDomainPoint); +#[serde_as] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct DomainPoint( + #[serde_as(as = "serialization::SerdeAs")] pub TpkeDomainPoint, +); impl DomainPoint { pub fn to_bytes(&self) -> Vec { - let mut bytes = vec![]; - CanonicalSerialize::serialize(&self.0, &mut bytes[..]).unwrap(); - bytes + bincode::serialize(&self).unwrap() } pub fn from_bytes(bytes: &[u8]) -> Self { - let mut reader = bytes; - let domain_point = - CanonicalDeserialize::deserialize(&mut reader).unwrap(); - Self(domain_point) + bincode::deserialize(bytes).unwrap() } } @@ -93,7 +93,7 @@ impl DecryptionShareSimplePrecomputed { } pub fn from_bytes(bytes: &[u8]) -> Self { - Self(TpkeDecryptionShareSimplePrecomputed::from_bytes(bytes).unwrap()) + Self(TpkeDecryptionShareSimplePrecomputed::from_bytes(bytes)) } } diff --git a/tpke/src/ciphertext.rs b/tpke/src/ciphertext.rs index 1baf4bef..0dee4fee 100644 --- a/tpke/src/ciphertext.rs +++ b/tpke/src/ciphertext.rs @@ -1,51 +1,55 @@ -use ark_ec::{AffineCurve, PairingEngine}; -use ark_ff::{One, ToBytes, UniformRand}; -use ark_serialize::CanonicalSerialize; +use std::ops::Mul; + +use ark_ec::pairing::Pairing; +use ark_ec::AffineRepr; +use ark_ff::{One, UniformRand}; +use ark_serialize::{CanonicalSerialize, Compress}; use chacha20poly1305::{ aead::{generic_array::GenericArray, Aead, KeyInit}, ChaCha20Poly1305, Nonce, }; use crypto::{digest::Digest, sha2::Sha256}; -use rand_core::RngCore; +use ferveo_common::serialization; use serde::{Deserialize, Serialize}; use serde_with::serde_as; -use crate::serialization; use crate::{htp_bls12381_g2, Result, ThresholdEncryptionError}; #[serde_as] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Ciphertext { +pub struct Ciphertext { #[serde_as(as = "serialization::SerdeAs")] - pub commitment: E::G1Affine, - // U + pub commitment: E::G1Affine, // U #[serde_as(as = "serialization::SerdeAs")] - pub auth_tag: E::G2Affine, - // W + pub auth_tag: E::G2Affine, // W + // #[serde(with = "serde_bytes")] // TODO: Consider using serde_bytes for raw bytes pub ciphertext: Vec, // V } -impl Ciphertext { +impl Ciphertext { pub fn check(&self, g_inv: &E::G1Prepared) -> bool { let hash_g2 = E::G2Prepared::from(self.construct_tag_hash()); - E::product_of_pairings(&[ - (E::G1Prepared::from(self.commitment), hash_g2), - (g_inv.clone(), E::G2Prepared::from(self.auth_tag)), - ]) == E::Fqk::one() + E::multi_pairing( + [self.commitment.into(), g_inv.to_owned()], + [hash_g2, self.auth_tag.into()], + ) + .0 == E::TargetField::one() } fn construct_tag_hash(&self) -> E::G2Affine { let mut hash_input = Vec::::new(); - self.commitment.write(&mut hash_input).unwrap(); + self.commitment + .serialize_uncompressed(&mut hash_input) + .unwrap(); hash_input.extend_from_slice(&self.ciphertext); hash_to_g2(&hash_input) } pub fn serialized_length(&self) -> usize { - self.commitment.serialized_size() - + self.auth_tag.serialized_size() + self.commitment.serialized_size(Compress::No) + + self.auth_tag.serialized_size(Compress::No) + self.ciphertext.len() } @@ -58,22 +62,22 @@ impl Ciphertext { } } -pub fn encrypt( +pub fn encrypt( message: &[u8], aad: &[u8], pubkey: &E::G1Affine, - rng: &mut R, + rng: &mut impl rand::Rng, ) -> Ciphertext { // r - let rand_element = E::Fr::rand(rng); + let rand_element = E::ScalarField::rand(rng); // g - let g_gen = E::G1Affine::prime_subgroup_generator(); + let g_gen = E::G1Affine::generator(); // h - let h_gen = E::G2Affine::prime_subgroup_generator(); + let h_gen = E::G2Affine::generator(); let ry_prep = E::G1Prepared::from(pubkey.mul(rand_element).into()); // s - let product = E::product_of_pairings(&[(ry_prep, h_gen.into())]); + let product = E::pairing(ry_prep, h_gen).0; // u let commitment = g_gen.mul(rand_element).into(); @@ -96,7 +100,7 @@ pub fn encrypt( /// Implements the check section 4.4.2 of the Ferveo paper, 'TPKE.CheckCiphertextValidity(U,W,aad)' /// See: https://eprint.iacr.org/2022/898.pdf /// See: https://nikkolasg.github.io/ferveo/tpke.html#to-validate-ciphertext-for-ind-cca2-security -pub fn check_ciphertext_validity( +pub fn check_ciphertext_validity( c: &Ciphertext, aad: &[u8], g_inv: &E::G1Prepared, @@ -108,11 +112,12 @@ pub fn check_ciphertext_validity( aad, )); - let is_ciphertext_valid = E::product_of_pairings(&[ + let is_ciphertext_valid = E::multi_pairing( // e(U, H_G2(U, aad)) = e(G, W) - (E::G1Prepared::from(c.commitment), hash_g2), - (g_inv.clone(), E::G2Prepared::from(c.auth_tag)), - ]) == E::Fqk::one(); + [c.commitment.into(), g_inv.to_owned()], + [hash_g2, c.auth_tag.into()], + ) + .0 == E::TargetField::one(); if is_ciphertext_valid { Ok(()) @@ -121,23 +126,24 @@ pub fn check_ciphertext_validity( } } -pub fn decrypt_symmetric( +pub fn decrypt_symmetric( ciphertext: &Ciphertext, aad: &[u8], private_key: &E::G2Affine, g_inv: &E::G1Prepared, ) -> Result> { check_ciphertext_validity(ciphertext, aad, g_inv)?; - let shared_secret = E::product_of_pairings(&[( + let shared_secret = E::pairing( E::G1Prepared::from(ciphertext.commitment), E::G2Prepared::from(*private_key), - )]); + ) + .0; decrypt_with_shared_secret_unchecked(ciphertext, &shared_secret) } -fn decrypt_with_shared_secret_unchecked( +fn decrypt_with_shared_secret_unchecked( ciphertext: &Ciphertext, - shared_secret: &E::Fqk, + shared_secret: &E::TargetField, ) -> Result> { let nonce = nonce_from_commitment::(ciphertext.commitment); let ciphertext = ciphertext.ciphertext.to_vec(); @@ -150,10 +156,10 @@ fn decrypt_with_shared_secret_unchecked( Ok(plaintext) } -pub fn decrypt_with_shared_secret( +pub fn decrypt_with_shared_secret( ciphertext: &Ciphertext, aad: &[u8], - shared_secret: &E::Fqk, + shared_secret: &E::TargetField, g_inv: &E::G1Prepared, ) -> Result> { check_ciphertext_validity(ciphertext, aad, g_inv)?; @@ -168,51 +174,49 @@ fn sha256(input: &[u8]) -> Vec { result.to_vec() } -pub fn shared_secret_to_chacha( - s: &E::Fqk, +pub fn shared_secret_to_chacha( + s: &E::TargetField, ) -> ChaCha20Poly1305 { let mut prf_key = Vec::new(); - s.write(&mut prf_key).unwrap(); + s.serialize_uncompressed(&mut prf_key).unwrap(); let prf_key_32 = sha256(&prf_key); ChaCha20Poly1305::new(GenericArray::from_slice(&prf_key_32)) } -fn nonce_from_commitment(commitment: E::G1Affine) -> Nonce { +fn nonce_from_commitment(commitment: E::G1Affine) -> Nonce { let mut commitment_bytes = Vec::new(); commitment - .serialize_unchecked(&mut commitment_bytes) + .serialize_uncompressed(&mut commitment_bytes) .unwrap(); let commitment_hash = sha256(&commitment_bytes); *Nonce::from_slice(&commitment_hash[..12]) } fn hash_to_g2(message: &[u8]) -> T { - let mut point_ser: Vec = Vec::new(); let point = htp_bls12381_g2(message); - point.serialize(&mut point_ser).unwrap(); - T::deserialize(&point_ser[..]).unwrap() + let mut point_ser: Vec = Vec::new(); + point.serialize_uncompressed(&mut point_ser).unwrap(); + T::deserialize_uncompressed(&point_ser[..]).unwrap() } -fn construct_tag_hash( - u: E::G1Affine, +fn construct_tag_hash( + commitment: E::G1Affine, stream_ciphertext: &[u8], aad: &[u8], ) -> E::G2Affine { let mut hash_input = Vec::::new(); - u.write(&mut hash_input).unwrap(); + commitment.serialize_uncompressed(&mut hash_input).unwrap(); hash_input.extend_from_slice(stream_ciphertext); hash_input.extend_from_slice(aad); - hash_to_g2(&hash_input) } #[cfg(test)] mod tests { use ark_bls12_381::G1Projective; - use ark_ec::ProjectiveCurve; + use ark_ec::CurveGroup; use ark_std::{test_rng, UniformRand}; - use rand::prelude::StdRng; use crate::test_common::*; use crate::*; @@ -226,7 +230,7 @@ mod tests { let aad: &[u8] = "my-aad".as_bytes(); let pubkey = G1Projective::rand(rng).into_affine(); - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); let deserialized: Ciphertext = Ciphertext::from_bytes(&ciphertext.to_bytes()); @@ -245,7 +249,7 @@ mod tests { setup_fast::(threshold, shares_num, rng); let g_inv = &contexts[0].setup_params.g_inv; - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); let plaintext = decrypt_symmetric(&ciphertext, aad, &privkey, g_inv).unwrap(); @@ -262,7 +266,7 @@ mod tests { let aad: &[u8] = "my-aad".as_bytes(); let (pubkey, _, contexts) = setup_fast::(threshold, shares_num, rng); let g_inv = contexts[0].setup_params.g_inv.clone(); - let mut ciphertext = encrypt::(msg, aad, &pubkey, rng); + let mut ciphertext = encrypt::(msg, aad, &pubkey, rng); // So far, the ciphertext is valid assert!(check_ciphertext_validity(&ciphertext, aad, &g_inv).is_ok()); diff --git a/tpke/src/combine.rs b/tpke/src/combine.rs index e0c05044..ec094d97 100644 --- a/tpke/src/combine.rs +++ b/tpke/src/combine.rs @@ -1,6 +1,8 @@ #![allow(non_snake_case)] -use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; +use std::ops::Mul; + +use ark_ec::{pairing::Pairing, CurveGroup}; use ark_ff::{Field, One, PrimeField, Zero}; use itertools::izip; use subproductdomain::SubproductDomain; @@ -11,18 +13,18 @@ use crate::{ PublicDecryptionContextFast, Result, ThresholdEncryptionError, }; -pub fn prepare_combine_fast( +pub fn prepare_combine_fast( public_decryption_contexts: &[PublicDecryptionContextFast], shares: &[DecryptionShareFast], ) -> Vec { let mut domain = vec![]; // omega_i, vector of domain points - let mut n_0 = E::Fr::one(); + let mut n_0 = E::ScalarField::one(); for d_i in shares.iter() { domain.push(public_decryption_contexts[d_i.decrypter_index].domain); // n_0_i = 1 * t^1 * t^2 ... n_0 *= public_decryption_contexts[d_i.decrypter_index].lagrange_n_0; } - let s = SubproductDomain::::new(domain); + let s = SubproductDomain::::new(domain); let mut lagrange = s.inverse_lagrange_coefficients(); // 1/L_i // Given a vector of field elements {v_i}, compute the vector {coeff * v_i^(-1)} @@ -42,22 +44,22 @@ pub fn prepare_combine_fast( .collect::>() } -pub fn prepare_combine_simple( - domain: &[E::Fr], -) -> Vec { +pub fn prepare_combine_simple( + domain: &[E::ScalarField], +) -> Vec { // In this formula x_i = 0, hence numerator is x_m // See https://en.wikipedia.org/wiki/Lagrange_polynomial#Optimal_algorithm - lagrange_basis_at::(domain, &E::Fr::zero()) + lagrange_basis_at::(domain, &E::ScalarField::zero()) } /// Calculate lagrange coefficients using optimized formula -pub fn lagrange_basis_at( - shares_x: &[E::Fr], - x_i: &E::Fr, -) -> Vec<::Fr> { +pub fn lagrange_basis_at( + shares_x: &[E::ScalarField], + x_i: &E::ScalarField, +) -> Vec<::ScalarField> { let mut lagrange_coeffs = vec![]; for x_j in shares_x { - let mut prod = E::Fr::one(); + let mut prod = E::ScalarField::one(); for x_m in shares_x { if x_j != x_m { prod *= (*x_m - x_i) / (*x_m - *x_j); @@ -69,32 +71,35 @@ pub fn lagrange_basis_at( } // TODO: Hide this from external users. Currently blocked by usage in benchmarks. -pub fn share_combine_fast_unchecked( +pub fn share_combine_fast_unchecked( shares: &[DecryptionShareFast], prepared_key_shares: &[E::G2Prepared], -) -> E::Fqk { - let mut pairing_product: Vec<(E::G1Prepared, E::G2Prepared)> = vec![]; +) -> E::TargetField { + let mut pairing_a = vec![]; + let mut pairing_b = vec![]; for (d_i, prepared_key_share) in izip!(shares, prepared_key_shares.iter()) { - // e(D_i, [b*omega_i^-1] Z_{i,omega_i}) - pairing_product.push(( + pairing_a.push( // D_i E::G1Prepared::from(d_i.decryption_share), + ); + pairing_b.push( // Z_{i,omega_i}) = [dk_{i}^{-1}]*\hat{Y}_{i_omega_j}] // Reference: https://nikkolasg.github.io/ferveo/pvss.html#validator-decryption-of-private-key-shares // Prepared key share is a sum of L_i * [b]Z_i prepared_key_share.clone(), - )); + ); } - E::product_of_pairings(&pairing_product) + // e(D_i, [b*omega_i^-1] Z_{i,omega_i}) + E::multi_pairing(pairing_a, pairing_b).0 } -pub fn share_combine_fast( +pub fn share_combine_fast( pub_contexts: &[PublicDecryptionContextFast], ciphertext: &Ciphertext, decryption_shares: &[DecryptionShareFast], prepared_key_shares: &[E::G2Prepared], -) -> Result { +) -> Result { let is_valid_shares = verify_decryption_shares_fast( pub_contexts, ciphertext, @@ -111,51 +116,52 @@ pub fn share_combine_fast( )) } -pub fn share_combine_simple( +pub fn share_combine_simple( decryption_shares: &[DecryptionShareSimple], - lagrange_coeffs: &[E::Fr], -) -> E::Fqk { + lagrange_coeffs: &[E::ScalarField], +) -> E::TargetField { // Sum of C_i^{L_i}z izip!(decryption_shares, lagrange_coeffs).fold( - E::Fqk::one(), + E::TargetField::one(), |acc, (c_i, alpha_i)| { - acc * c_i.decryption_share.pow(alpha_i.into_repr()) + acc * c_i.decryption_share.pow(alpha_i.into_bigint()) }, ) } -pub fn share_combine_simple_precomputed( +pub fn share_combine_simple_precomputed( shares: &[DecryptionShareSimplePrecomputed], -) -> E::Fqk { +) -> E::TargetField { // s = ∏ C_{λ_i}, where λ_i is the Lagrange coefficient for i shares .iter() - .fold(E::Fqk::one(), |acc, c_i| acc * c_i.decryption_share) + .fold(E::TargetField::one(), |acc, c_i| acc * c_i.decryption_share) } #[cfg(test)] mod tests { - type Fr = ::Fr; + type ScalarField = + ::ScalarField; #[test] fn test_lagrange() { use ark_poly::EvaluationDomain; use ark_std::One; let fft_domain = - ark_poly::Radix2EvaluationDomain::::new(500).unwrap(); + ark_poly::Radix2EvaluationDomain::::new(500).unwrap(); let mut domain = Vec::with_capacity(500); - let mut point = Fr::one(); + let mut point = ScalarField::one(); for _ in 0..500 { domain.push(point); point *= fft_domain.group_gen; } - let mut lagrange_n_0 = domain.iter().product::(); + let mut lagrange_n_0 = domain.iter().product::(); if domain.len() % 2 == 1 { lagrange_n_0 = -lagrange_n_0; } - let s = subproductdomain::SubproductDomain::::new(domain); + let s = subproductdomain::SubproductDomain::::new(domain); let mut lagrange = s.inverse_lagrange_coefficients(); ark_ff::batch_inversion_and_mul(&mut lagrange, &lagrange_n_0); } diff --git a/tpke/src/context.rs b/tpke/src/context.rs index aa99ca90..5ba408b6 100644 --- a/tpke/src/context.rs +++ b/tpke/src/context.rs @@ -1,4 +1,7 @@ -use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; +use std::ops::Mul; + +use ark_ec::pairing::Pairing; +use ark_ec::CurveGroup; use crate::{ check_ciphertext_validity, prepare_combine_simple, BlindedKeyShare, @@ -7,28 +10,28 @@ use crate::{ }; #[derive(Clone, Debug)] -pub struct PublicDecryptionContextFast { - pub domain: E::Fr, +pub struct PublicDecryptionContextFast { + pub domain: E::ScalarField, pub public_key_share: PublicKeyShare, pub blinded_key_share: BlindedKeyShare, // This decrypter's contribution to N(0), namely (-1)^|domain| * \prod_i omega_i - pub lagrange_n_0: E::Fr, + pub lagrange_n_0: E::ScalarField, pub h_inv: E::G2Prepared, } #[derive(Clone, Debug)] -pub struct PublicDecryptionContextSimple { - pub domain: E::Fr, +pub struct PublicDecryptionContextSimple { + pub domain: E::ScalarField, pub public_key_share: PublicKeyShare, pub blinded_key_share: BlindedKeyShare, pub h: E::G2Affine, - pub validator_public_key: E::G2Projective, + pub validator_public_key: E::G2, } #[derive(Clone, Debug)] -pub struct SetupParams { - pub b: E::Fr, - pub b_inv: E::Fr, +pub struct SetupParams { + pub b: E::ScalarField, + pub b_inv: E::ScalarField, pub g: E::G1Affine, pub g_inv: E::G1Prepared, pub h_inv: E::G2Prepared, @@ -36,14 +39,14 @@ pub struct SetupParams { } #[derive(Clone, Debug)] -pub struct PrivateDecryptionContextFast { +pub struct PrivateDecryptionContextFast { pub index: usize, pub setup_params: SetupParams, pub private_key_share: PrivateKeyShare, pub public_decryption_contexts: Vec>, } -impl PrivateDecryptionContextFast { +impl PrivateDecryptionContextFast { pub fn create_share( &self, ciphertext: &Ciphertext, @@ -68,16 +71,16 @@ impl PrivateDecryptionContextFast { } #[derive(Clone, Debug)] -pub struct PrivateDecryptionContextSimple { +pub struct PrivateDecryptionContextSimple { pub index: usize, pub setup_params: SetupParams, pub private_key_share: PrivateKeyShare, pub public_decryption_contexts: Vec>, // TODO: Remove/replace with `setup_params.b` after refactoring - pub validator_private_key: E::Fr, + pub validator_private_key: E::ScalarField, } -impl PrivateDecryptionContextSimple { +impl PrivateDecryptionContextSimple { pub fn create_share( &self, ciphertext: &Ciphertext, diff --git a/tpke/src/decryption.rs b/tpke/src/decryption.rs index f3baf18b..45cc909d 100644 --- a/tpke/src/decryption.rs +++ b/tpke/src/decryption.rs @@ -1,29 +1,30 @@ +use std::marker::PhantomData; +use std::ops::Mul; + use anyhow::Result; -use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; -use ark_ff::{Field, One, PrimeField, Zero}; -use ark_serialize::{ - CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write, -}; +use ark_ec::pairing::Pairing; +use ark_ec::CurveGroup; +use ark_ff::{Field, One, Zero}; +use ferveo_common::serialization; use itertools::{izip, zip_eq}; use rand_core::RngCore; -use serde::{Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_with::serde_as; use crate::{ - check_ciphertext_validity, generate_random, serialization, Ciphertext, - PrivateKeyShare, PublicDecryptionContextFast, - PublicDecryptionContextSimple, + check_ciphertext_validity, generate_random, Ciphertext, PrivateKeyShare, + PublicDecryptionContextFast, PublicDecryptionContextSimple, }; #[serde_as] #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct DecryptionShareFast { +pub struct DecryptionShareFast { pub decrypter_index: usize, #[serde_as(as = "serialization::SerdeAs")] pub decryption_share: E::G1Affine, } -impl DecryptionShareFast { +impl DecryptionShareFast { pub fn to_bytes(&self) -> Vec { bincode::serialize(&self).unwrap() } @@ -33,14 +34,16 @@ impl DecryptionShareFast { } } -#[derive(CanonicalSerialize, CanonicalDeserialize, Debug, Clone, PartialEq)] -pub struct ValidatorShareChecksum { +#[serde_as] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub struct ValidatorShareChecksum { + #[serde_as(as = "serialization::SerdeAs")] pub checksum: E::G1Affine, } -impl ValidatorShareChecksum { +impl ValidatorShareChecksum { pub fn new( - validator_decryption_key: &E::Fr, + validator_decryption_key: &E::ScalarField, ciphertext: &Ciphertext, ) -> Self { // C_i = dk_i^{-1} * U @@ -53,14 +56,14 @@ impl ValidatorShareChecksum { pub fn verify( &self, - decryption_share: &E::Fqk, + decryption_share: &E::TargetField, share_aggregate: &E::G2Affine, validator_public_key: &E::G2Affine, - h: &E::G2Projective, + h: &E::G2, ciphertext: &Ciphertext, ) -> bool { // D_i == e(C_i, Y_i) - if *decryption_share != E::pairing(self.checksum, *share_aggregate) { + if *decryption_share != E::pairing(self.checksum, *share_aggregate).0 { return false; } @@ -75,33 +78,35 @@ impl ValidatorShareChecksum { } pub fn from_bytes(bytes: &[u8]) -> Self { - CanonicalDeserialize::deserialize(bytes).unwrap() + bincode::deserialize(bytes).unwrap() } pub fn to_bytes(&self) -> Vec { - let mut bytes = Vec::new(); - CanonicalSerialize::serialize(self, &mut bytes).unwrap(); - bytes + bincode::serialize(&self).unwrap() } } #[serde_as] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct DecryptionShareSimple { +#[serde(bound( + serialize = "ValidatorShareChecksum: Serialize", + deserialize = "ValidatorShareChecksum: DeserializeOwned" +))] +pub struct DecryptionShareSimple { // TODO: Add decryptor public key? Replace decryptor_index with public key? pub decrypter_index: usize, #[serde_as(as = "serialization::SerdeAs")] - pub decryption_share: E::Fqk, - #[serde(with = "ferveo_common::ark_serde")] + pub decryption_share: E::TargetField, pub validator_checksum: ValidatorShareChecksum, + phantom2: PhantomData, } -impl DecryptionShareSimple { +impl DecryptionShareSimple { /// Create a decryption share from the given parameters. /// This function checks that the ciphertext is valid. pub fn create( validator_index: usize, - validator_decryption_key: &E::Fr, + validator_decryption_key: &E::ScalarField, private_key_share: &PrivateKeyShare, ciphertext: &Ciphertext, aad: &[u8], @@ -120,7 +125,7 @@ impl DecryptionShareSimple { /// This function does not check that the ciphertext is valid. pub fn create_unchecked( validator_index: usize, - validator_decryption_key: &E::Fr, + validator_decryption_key: &E::ScalarField, private_key_share: &PrivateKeyShare, ciphertext: &Ciphertext, ) -> Self { @@ -128,7 +133,8 @@ impl DecryptionShareSimple { let decryption_share = E::pairing( ciphertext.commitment, private_key_share.private_key_share, - ); + ) + .0; let validator_checksum = ValidatorShareChecksum::new(validator_decryption_key, ciphertext); @@ -137,6 +143,7 @@ impl DecryptionShareSimple { decrypter_index: validator_index, decryption_share, validator_checksum, + phantom2: PhantomData, } } @@ -145,7 +152,7 @@ impl DecryptionShareSimple { &self, share_aggregate: &E::G2Affine, validator_public_key: &E::G2Affine, - h: &E::G2Projective, + h: &E::G2, ciphertext: &Ciphertext, ) -> bool { self.validator_checksum.verify( @@ -168,22 +175,25 @@ impl DecryptionShareSimple { #[serde_as] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct DecryptionShareSimplePrecomputed { +#[serde(bound( + serialize = "ValidatorShareChecksum: Serialize", + deserialize = "ValidatorShareChecksum: DeserializeOwned" +))] +pub struct DecryptionShareSimplePrecomputed { pub decrypter_index: usize, #[serde_as(as = "serialization::SerdeAs")] - pub decryption_share: E::Fqk, - #[serde(with = "ferveo_common::ark_serde")] + pub decryption_share: E::TargetField, pub validator_checksum: ValidatorShareChecksum, } -impl DecryptionShareSimplePrecomputed { +impl DecryptionShareSimplePrecomputed { pub fn new( validator_index: usize, - validator_decryption_key: &E::Fr, + validator_decryption_key: &E::ScalarField, private_key_share: &PrivateKeyShare, ciphertext: &Ciphertext, aad: &[u8], - lagrange_coeff: &E::Fr, + lagrange_coeff: &E::ScalarField, g_inv: &E::G1Prepared, ) -> Result { check_ciphertext_validity::(ciphertext, aad, g_inv)?; @@ -199,19 +209,19 @@ impl DecryptionShareSimplePrecomputed { pub fn create_unchecked( validator_index: usize, - validator_decryption_key: &E::Fr, + validator_decryption_key: &E::ScalarField, private_key_share: &PrivateKeyShare, ciphertext: &Ciphertext, - lagrange_coeff: &E::Fr, + lagrange_coeff: &E::ScalarField, ) -> Self { // U_{λ_i} = [λ_{i}(0)] U - let u_to_lagrange_coeff = - ciphertext.commitment.mul(lagrange_coeff.into_repr()); + let u_to_lagrange_coeff = ciphertext.commitment.mul(lagrange_coeff); // C_{λ_i} = e(U_{λ_i}, Z_i) let decryption_share = E::pairing( u_to_lagrange_coeff, private_key_share.private_key_share, - ); + ) + .0; let validator_checksum = ValidatorShareChecksum::new(validator_decryption_key, ciphertext); @@ -228,7 +238,7 @@ impl DecryptionShareSimplePrecomputed { &self, share_aggregate: &E::G2Affine, validator_public_key: &E::G2Affine, - h: &E::G2Projective, + h: &E::G2, ciphertext: &Ciphertext, ) -> bool { self.validator_checksum.verify( @@ -240,8 +250,8 @@ impl DecryptionShareSimplePrecomputed { ) } - pub fn from_bytes(bytes: &[u8]) -> Result { - Ok(bincode::deserialize(bytes).unwrap()) + pub fn from_bytes(bytes: &[u8]) -> Self { + bincode::deserialize(bytes).unwrap() } pub fn to_bytes(&self) -> Vec { @@ -250,7 +260,7 @@ impl DecryptionShareSimplePrecomputed { } // TODO: Remove this code? Currently only used in benchmarks. Move to benchmark suite? -pub fn batch_verify_decryption_shares( +pub fn batch_verify_decryption_shares( pub_contexts: &[PublicDecryptionContextFast], ciphertexts: &[Ciphertext], decryption_shares: &[Vec>], @@ -275,26 +285,28 @@ pub fn batch_verify_decryption_shares( .map(|_| generate_random::<_, E>(num_shares, rng)) .collect::>(); - let mut pairings = Vec::with_capacity(num_shares + 1); + let mut pairings_a = Vec::with_capacity(num_shares + 1); + let mut pairings_b = Vec::with_capacity(num_shares + 1); // Compute \sum_j \alpha_{i,j} for each ciphertext i let sum_alpha_i = alpha_ij .iter() - .map(|alpha_j| alpha_j.iter().sum::()) + .map(|alpha_j| alpha_j.iter().sum::()) .collect::>(); // Compute \sum_i [ \sum_j \alpha_{i,j} ] U_i let sum_u_i = E::G1Prepared::from( izip!(ciphertexts.iter(), sum_alpha_i.iter()) .map(|(c, alpha_j)| c.commitment.mul(*alpha_j)) - .sum::() + .sum::() .into_affine(), ); // e(\sum_i [ \sum_j \alpha_{i,j} ] U_i, -H) - pairings.push((sum_u_i, pub_contexts[0].h_inv.clone())); + pairings_a.push(sum_u_i); + pairings_b.push(pub_contexts[0].h_inv.clone()); - let mut sum_d_i = vec![E::G1Projective::zero(); num_shares]; + let mut sum_d_i = vec![E::G1::zero(); num_shares]; // sum_D_i = { [\sum_i \alpha_{i,j} ] D_i } for (d, alpha_j) in izip!(decryption_shares.iter(), alpha_ij.iter()) { @@ -307,13 +319,14 @@ pub fn batch_verify_decryption_shares( // e([\sum_i \alpha_{i,j} ] D_i, B_i) for (d_i, b_i) in izip!(sum_d_i.iter(), blinding_keys.iter()) { - pairings.push((E::G1Prepared::from(d_i.into_affine()), b_i.clone())); + pairings_a.push(E::G1Prepared::from(d_i.into_affine())); + pairings_b.push(b_i.clone()); } - E::product_of_pairings(&pairings) == E::Fqk::one() + E::multi_pairing(pairings_a, pairings_b).0 == E::TargetField::one() } -pub fn verify_decryption_shares_fast( +pub fn verify_decryption_shares_fast( pub_contexts: &[PublicDecryptionContextFast], ciphertext: &Ciphertext, decryption_shares: &[DecryptionShareFast], @@ -329,17 +342,20 @@ pub fn verify_decryption_shares_fast( }) .collect::>(); + let mut pairing_a: Vec = vec![]; + let mut pairing_b = vec![]; + // e(U, -H) - let pairing_a = ( - E::G1Prepared::from(ciphertext.commitment), - pub_contexts[0].h_inv.clone(), - ); + pairing_a.push(ciphertext.commitment.into()); + pairing_b.push(pub_contexts[0].h_inv.clone()); for (d_i, p_i) in zip_eq(decryption_shares, blinding_keys) { + let mut pairing_a_i = pairing_a.clone(); + let mut pairing_b_i = pairing_b.clone(); // e(D_i, B_i) - let pairing_b = (E::G1Prepared::from(d_i.decryption_share), p_i); - if E::product_of_pairings(&[pairing_a.clone(), pairing_b.clone()]) - != E::Fqk::one() + pairing_a_i.push(d_i.decryption_share.into()); + pairing_b_i.push(p_i.clone()); + if E::multi_pairing(pairing_a_i, pairing_b_i).0 != E::TargetField::one() { return false; } @@ -348,7 +364,7 @@ pub fn verify_decryption_shares_fast( true } -pub fn verify_decryption_shares_simple( +pub fn verify_decryption_shares_simple( pub_contexts: &Vec>, ciphertext: &Ciphertext, decryption_shares: &Vec>, @@ -363,7 +379,7 @@ pub fn verify_decryption_shares_simple( let is_valid = decryption_share.verify( y_i, &pub_context.validator_public_key.into_affine(), - &pub_context.h.into_projective(), + &pub_context.h.into(), ciphertext, ); if !is_valid { @@ -375,7 +391,7 @@ pub fn verify_decryption_shares_simple( #[cfg(test)] mod tests { - use ark_ec::AffineCurve; + use ark_ec::AffineRepr; use crate::*; @@ -385,8 +401,7 @@ mod tests { fn decryption_share_serialization() { let decryption_share = DecryptionShareFast:: { decrypter_index: 1, - decryption_share: ark_bls12_381::G1Affine::prime_subgroup_generator( - ), + decryption_share: ark_bls12_381::G1Affine::generator(), }; let serialized = decryption_share.to_bytes(); diff --git a/tpke/src/hash_to_curve.rs b/tpke/src/hash_to_curve.rs index 1d6795e1..78592a49 100644 --- a/tpke/src/hash_to_curve.rs +++ b/tpke/src/hash_to_curve.rs @@ -3,7 +3,9 @@ #![allow(clippy::zero_prefixed_literal)] #![allow(dead_code)] -use ark_serialize::CanonicalDeserialize; +use ark_bls12_381::g2::Config; +use ark_ec::short_weierstrass::Affine; +use ark_ec::AffineRepr; use miracl_core::bls12381::big::BIG; use miracl_core::bls12381::dbig::DBIG; use miracl_core::bls12381::ecp; @@ -73,11 +75,22 @@ pub fn htp_bls12381_g2(msg: &[u8]) -> ark_bls12_381::G2Affine { compressed_rev[000..=047].reverse(); compressed_rev[048..=095].reverse(); - ark_bls12_381::G2Affine::deserialize(&compressed_rev[..]).unwrap() + to_affine(&mut compressed_rev) +} + +fn to_affine(compressed_rev: &mut [u8; 96]) -> Affine { + // TODO: This is a hack to get around the fact that G2Affine representation produced by miracl_core + // is not compatible with the one used by arkworks. The "Unexpected Flag" error is thrown. + // ark_bls12_381::G2Affine::deserialize_compressed(&compressed_rev[..]) + // .unwrap() + // In this workaround we use `from_random_bytes` instead of `deserialize_compressed`, because + // the former performs checks that prevent the "Unexpected Flag" error. + ark_bls12_381::G2Affine::from_random_bytes(&compressed_rev[..]).unwrap() } #[cfg(test)] mod tests { + use super::*; fn test_hash_to_g2(msg: &[u8], expected_hex_string: &str) { @@ -89,13 +102,9 @@ mod tests { expected_compressed_rev[0] &= (1 << 5) - 1; expected_compressed_rev.reverse(); - let expected = - ark_bls12_381::G2Affine::deserialize(&expected_compressed_rev[..]) - .unwrap(); - + let expected = to_affine(&mut expected_compressed_rev); let res = htp_bls12381_g2(msg); - - assert!(res == expected) + assert_eq!(res, expected) } #[test] diff --git a/tpke/src/key_share.rs b/tpke/src/key_share.rs index c84dfc9e..52354348 100644 --- a/tpke/src/key_share.rs +++ b/tpke/src/key_share.rs @@ -1,36 +1,43 @@ -use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; +use std::ops::Mul; + +use ark_ec::pairing::Pairing; +use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::One; use ark_std::UniformRand; use rand_core::RngCore; #[derive(Debug, Clone)] -pub struct PublicKeyShare { +pub struct PublicKeyShare { pub public_key_share: E::G1Affine, // A_{i, \omega_i} } #[derive(Debug, Clone)] -pub struct BlindedKeyShare { - pub blinding_key: E::G2Affine, // [b] H - pub blinded_key_share: E::G2Affine, // [b] Z_{i, \omega_i} +pub struct BlindedKeyShare { + pub blinding_key: E::G2Affine, + // [b] H + pub blinded_key_share: E::G2Affine, + // [b] Z_{i, \omega_i} // TODO: Should we use this kind of optizmization here or anywhere else? pub blinding_key_prepared: E::G2Prepared, } -pub fn generate_random( +pub fn generate_random( n: usize, rng: &mut R, -) -> Vec { - (0..n).map(|_| E::Fr::rand(rng)).collect::>() +) -> Vec { + (0..n) + .map(|_| E::ScalarField::rand(rng)) + .collect::>() } -impl BlindedKeyShare { +impl BlindedKeyShare { pub fn verify_blinding( &self, public_key_share: &PublicKeyShare, rng: &mut R, ) -> bool { - let g = E::G1Affine::prime_subgroup_generator(); - let alpha = E::Fr::rand(rng); + let g = E::G1Affine::generator(); + let alpha = E::ScalarField::rand(rng); let alpha_a = E::G1Prepared::from( g + public_key_share.public_key_share.mul(alpha).into_affine(), @@ -42,27 +49,26 @@ impl BlindedKeyShare { ); // e(g, Yi) == e(Ai, [b] H) - E::product_of_pairings(&[ - (E::G1Prepared::from(-g), alpha_z), - (alpha_a, E::G2Prepared::from(self.blinding_key)), - ]) == E::Fqk::one() + let g_inv = E::G1Prepared::from(-g.into_group()); + E::multi_pairing([g_inv, alpha_a], [alpha_z, self.blinding_key.into()]) + .0 + == E::TargetField::one() } - pub fn multiply_by_omega_inv(&mut self, omega_inv: &E::Fr) { + pub fn multiply_by_omega_inv(&mut self, omega_inv: &E::ScalarField) { self.blinded_key_share = self.blinded_key_share.mul(-*omega_inv).into_affine(); } } #[derive(Debug, Clone, PartialEq)] -pub struct PrivateKeyShare { +pub struct PrivateKeyShare { pub private_key_share: E::G2Affine, } -impl PrivateKeyShare { - pub fn blind(&self, b: E::Fr) -> BlindedKeyShare { - let blinding_key = - E::G2Affine::prime_subgroup_generator().mul(b).into_affine(); +impl PrivateKeyShare { + pub fn blind(&self, b: E::ScalarField) -> BlindedKeyShare { + let blinding_key = E::G2Affine::generator().mul(b).into_affine(); BlindedKeyShare:: { blinding_key, blinding_key_prepared: E::G2Prepared::from(blinding_key), diff --git a/tpke/src/lib.rs b/tpke/src/lib.rs index 28023b86..b8313235 100644 --- a/tpke/src/lib.rs +++ b/tpke/src/lib.rs @@ -25,7 +25,6 @@ pub use refresh::*; // TODO: Turn into a crate features pub mod api; -pub mod serialization; #[derive(Debug, thiserror::Error)] pub enum ThresholdEncryptionError { @@ -57,22 +56,23 @@ pub type Result = anyhow::Result; /// Factory functions for testing #[cfg(any(test, feature = "test-common"))] pub mod test_common { + use std::ops::Mul; use std::usize; pub use ark_bls12_381::Bls12_381 as EllipticCurve; - use ark_ec::{AffineCurve, PairingEngine}; + use ark_ec::{pairing::Pairing, AffineRepr}; pub use ark_ff::UniformRand; use ark_ff::{Field, One, Zero}; use ark_poly::univariate::DensePolynomial; - use ark_poly::Polynomial; - use ark_poly::{EvaluationDomain, UVPolynomial}; + use ark_poly::DenseUVPolynomial; + use ark_poly::{EvaluationDomain, Polynomial}; use itertools::izip; use rand_core::RngCore; use subproductdomain::fast_multiexp; pub use super::*; - pub fn setup_fast( + pub fn setup_fast( threshold: usize, shares_num: usize, rng: &mut impl RngCore, @@ -84,24 +84,26 @@ pub mod test_common { assert!(shares_num >= threshold); // Generators G∈G1, H∈G2 - let g = E::G1Affine::prime_subgroup_generator(); - let h = E::G2Affine::prime_subgroup_generator(); + let g = E::G1Affine::generator(); + let h = E::G2Affine::generator(); // The dealer chooses a uniformly random polynomial f of degree t-1 - let threshold_poly = DensePolynomial::::rand(threshold - 1, rng); + let threshold_poly = + DensePolynomial::::rand(threshold - 1, rng); // Domain, or omega Ω let fft_domain = - ark_poly::Radix2EvaluationDomain::::new(shares_num).unwrap(); + ark_poly::Radix2EvaluationDomain::::new(shares_num) + .unwrap(); // `evals` are evaluations of the polynomial f over the domain, omega: f(ω_j) for ω_j in Ω let evals = threshold_poly.evaluate_over_domain_by_ref(fft_domain); // A - public key shares of participants - let pubkey_shares = fast_multiexp(&evals.evals, g.into_projective()); + let pubkey_shares = fast_multiexp(&evals.evals, g.into_group()); let pubkey_share = g.mul(evals.evals[0]); debug_assert!(pubkey_shares[0] == E::G1Affine::from(pubkey_share)); // Y, but only when b = 1 - private key shares of participants - let privkey_shares = fast_multiexp(&evals.evals, h.into_projective()); + let privkey_shares = fast_multiexp(&evals.evals, h.into_group()); // a_0 let x = threshold_poly.coeffs[0]; @@ -111,9 +113,9 @@ pub mod test_common { let privkey = h.mul(x); let mut domain_points = Vec::with_capacity(shares_num); - let mut point = E::Fr::one(); + let mut point = E::ScalarField::one(); let mut domain_points_inv = Vec::with_capacity(shares_num); - let mut point_inv = E::Fr::one(); + let mut point_inv = E::ScalarField::one(); for _ in 0..shares_num { domain_points.push(point); // 1, t, t^2, t^3, ...; where t is a scalar generator fft_domain.group_gen @@ -137,7 +139,7 @@ pub mod test_common { let private_key_share = PrivateKeyShare:: { private_key_share: *private, }; - let b = E::Fr::rand(rng); + let b = E::ScalarField::rand(rng); let mut blinded_key_shares = private_key_share.blind(b); blinded_key_shares.multiply_by_omega_inv(domain_inv); private_contexts.push(PrivateDecryptionContextFast:: { @@ -146,8 +148,8 @@ pub mod test_common { b, b_inv: b.inverse().unwrap(), g, - h_inv: E::G2Prepared::from(-h), - g_inv: E::G1Prepared::from(-g), + h_inv: E::G2Prepared::from(-h.into_group()), + g_inv: E::G1Prepared::from(-g.into_group()), h, }, private_key_share, @@ -160,7 +162,7 @@ pub mod test_common { }, blinded_key_share: blinded_key_shares, lagrange_n_0: *domain, - h_inv: E::G2Prepared::from(-h), + h_inv: E::G2Prepared::from(-h.into_group()), }); } for private in private_contexts.iter_mut() { @@ -170,10 +172,10 @@ pub mod test_common { (pubkey.into(), privkey.into(), private_contexts) } - pub fn setup_simple( + pub fn setup_simple( threshold: usize, shares_num: usize, - rng: &mut impl RngCore, + rng: &mut impl rand::Rng, ) -> ( E::G1Affine, E::G2Affine, @@ -181,26 +183,28 @@ pub mod test_common { ) { assert!(shares_num >= threshold); - let g = E::G1Affine::prime_subgroup_generator(); - let h = E::G2Affine::prime_subgroup_generator(); + let g = E::G1Affine::generator(); + let h = E::G2Affine::generator(); // The dealer chooses a uniformly random polynomial f of degree t-1 - let threshold_poly = DensePolynomial::::rand(threshold - 1, rng); + let threshold_poly = + DensePolynomial::::rand(threshold - 1, rng); // Domain, or omega Ω let fft_domain = - ark_poly::Radix2EvaluationDomain::::new(shares_num).unwrap(); + ark_poly::Radix2EvaluationDomain::::new(shares_num) + .unwrap(); // `evals` are evaluations of the polynomial f over the domain, omega: f(ω_j) for ω_j in Ω let evals = threshold_poly.evaluate_over_domain_by_ref(fft_domain); let shares_x = fft_domain.elements().collect::>(); // A - public key shares of participants - let pubkey_shares = fast_multiexp(&evals.evals, g.into_projective()); + let pubkey_shares = fast_multiexp(&evals.evals, g.into_group()); let pubkey_share = g.mul(evals.evals[0]); debug_assert!(pubkey_shares[0] == E::G1Affine::from(pubkey_share)); // Y, but only when b = 1 - private key shares of participants - let privkey_shares = fast_multiexp(&evals.evals, h.into_projective()); + let privkey_shares = fast_multiexp(&evals.evals, h.into_group()); // a_0 let x = threshold_poly.coeffs[0]; @@ -208,7 +212,7 @@ pub mod test_common { let pubkey = g.mul(x); let privkey = h.mul(x); - let secret = threshold_poly.evaluate(&E::Fr::zero()); + let secret = threshold_poly.evaluate(&E::ScalarField::zero()); debug_assert!(secret == x); let mut private_contexts = vec![]; @@ -222,7 +226,7 @@ pub mod test_common { let private_key_share = PrivateKeyShare:: { private_key_share: *private, }; - let b = E::Fr::rand(rng); + let b = E::ScalarField::rand(rng); let blinded_key_share = private_key_share.blind(b); private_contexts.push(PrivateDecryptionContextSimple:: { index, @@ -230,8 +234,8 @@ pub mod test_common { b, b_inv: b.inverse().unwrap(), g, - h_inv: E::G2Prepared::from(-h), - g_inv: E::G1Prepared::from(-g), + h_inv: E::G2Prepared::from(-h.into_group()), + g_inv: E::G1Prepared::from(-g.into_group()), h, }, private_key_share, @@ -261,11 +265,12 @@ mod tests { use std::collections::HashMap; use std::ops::Mul; - use ark_bls12_381::{Fr, FrParameters}; - use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; - use ark_ff::{BigInteger256, Fp256, Zero}; + use ark_bls12_381::Fr; + use ark_ec::pairing::Pairing; + use ark_ec::{AffineRepr, CurveGroup}; + use ark_ff::Zero; use ark_std::{test_rng, UniformRand}; - use rand::prelude::StdRng; + use rand_core::RngCore; use crate::refresh::{ make_random_polynomial_at, prepare_share_updates_for_recovery, @@ -276,14 +281,15 @@ mod tests { use crate::test_common::*; type E = ark_bls12_381::Bls12_381; - type Fqk = ::Fqk; + type TargetField = ::TargetField; + type ScalarField = ::ScalarField; - fn make_shared_secret_from_contexts( + fn make_shared_secret_from_contexts( contexts: &[PrivateDecryptionContextSimple], ciphertext: &Ciphertext, aad: &[u8], _g_inv: &E::G1Prepared, - ) -> E::Fqk { + ) -> E::TargetField { let decryption_shares: Vec<_> = contexts .iter() .map(|c| c.create_share(ciphertext, aad).unwrap()) @@ -304,7 +310,7 @@ mod tests { let (pubkey, _, _) = setup_fast::(threshold, shares_num, rng); - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); let serialized = ciphertext.to_bytes(); let deserialized: Ciphertext = Ciphertext::from_bytes(&serialized); @@ -312,11 +318,11 @@ mod tests { assert_eq!(serialized, deserialized.to_bytes()) } - fn test_ciphertext_validation_fails( + fn test_ciphertext_validation_fails( msg: &[u8], aad: &[u8], ciphertext: &Ciphertext, - shared_secret: &E::Fqk, + shared_secret: &E::TargetField, g_inv: &E::G1Prepared, ) { // So far, the ciphertext is valid @@ -332,7 +338,7 @@ mod tests { &ciphertext, aad, shared_secret, - g_inv + g_inv, ) .is_err()); @@ -342,15 +348,15 @@ mod tests { &ciphertext, aad, shared_secret, - g_inv + g_inv, ) .is_err()); } - fn make_new_share_fragments( - rng: &mut StdRng, + fn make_new_share_fragments( + rng: &mut R, threshold: usize, - x_r: &Fp256, + x_r: &Fr, remaining_participants: &[PrivateDecryptionContextSimple], ) -> Vec> { // Each participant prepares an update for each other participant @@ -395,10 +401,10 @@ mod tests { new_share_fragments } - fn make_shared_secret( + fn make_shared_secret( pub_contexts: &[PublicDecryptionContextSimple], decryption_shares: &[DecryptionShareSimple], - ) -> E::Fqk { + ) -> E::TargetField { let domain = pub_contexts.iter().map(|c| c.domain).collect::>(); let lagrange_coeffs = prepare_combine_simple::(&domain); share_combine_simple::(decryption_shares, &lagrange_coeffs) @@ -413,7 +419,7 @@ mod tests { let aad: &[u8] = "my-aad".as_bytes(); let (pubkey, _, contexts) = setup_fast::(threshold, shares_num, rng); - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); let bad_aad = "bad aad".as_bytes(); assert!(contexts[0].create_share(&ciphertext, bad_aad).is_err()); @@ -429,7 +435,7 @@ mod tests { let (pubkey, _, contexts) = setup_simple::(threshold, shares_num, rng); - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); let bad_aad = "bad aad".as_bytes(); assert!(contexts[0].create_share(&ciphertext, bad_aad).is_err()); @@ -445,7 +451,7 @@ mod tests { let (pubkey, _, contexts) = setup_fast::(threshold, shares_num, &mut rng); - let ciphertext = encrypt::<_, E>(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); let g_inv = &contexts[0].setup_params.g_inv; let mut decryption_shares: Vec> = vec![]; @@ -495,7 +501,7 @@ mod tests { setup_simple::(threshold, shares_num, &mut rng); let g_inv = &contexts[0].setup_params.g_inv; - let ciphertext = encrypt::<_, E>(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); let decryption_shares: Vec<_> = contexts .iter() @@ -527,7 +533,7 @@ mod tests { let (pubkey, _, contexts) = setup_simple::(threshold, shares_num, &mut rng); let g_inv = &contexts[0].setup_params.g_inv; - let ciphertext = encrypt::<_, E>(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); let decryption_shares: Vec<_> = contexts .iter() @@ -573,7 +579,7 @@ mod tests { let (pubkey, _, contexts) = setup_simple::(threshold, shares_num, &mut rng); - let ciphertext = encrypt::<_, E>(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); let decryption_shares: Vec<_> = contexts .iter() @@ -602,24 +608,24 @@ mod tests { has_bad_checksum.validator_checksum.checksum = has_bad_checksum .validator_checksum .checksum - .mul(BigInteger256::rand(rng)) + .mul(ScalarField::rand(rng)) .into_affine(); assert!(!has_bad_checksum.verify( &pub_contexts[0].blinded_key_share.blinded_key_share, &pub_contexts[0].validator_public_key.into_affine(), - &pub_contexts[0].h.into_projective(), + &pub_contexts[0].h.into_group(), &ciphertext, )); let mut has_bad_share = decryption_shares[0].clone(); has_bad_share.decryption_share = - has_bad_share.decryption_share.mul(Fqk::rand(rng)); + has_bad_share.decryption_share.mul(TargetField::rand(rng)); assert!(!has_bad_share.verify( &pub_contexts[0].blinded_key_share.blinded_key_share, &pub_contexts[0].validator_public_key.into_affine(), - &pub_contexts[0].h.into_projective(), + &pub_contexts[0].h.into_group(), &ciphertext, )); } @@ -688,7 +694,7 @@ mod tests { let (pubkey, _, contexts) = setup_simple::(threshold, shares_num, rng); let g_inv = &contexts[0].setup_params.g_inv; - let ciphertext = encrypt::<_, E>(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); // Create an initial shared secret let old_shared_secret = make_shared_secret_from_contexts( @@ -701,7 +707,7 @@ mod tests { // Now, we're going to recover a new share at a random point and check that the shared secret is still the same // Our random point - let x_r = Fr::rand(rng); + let x_r = ScalarField::rand(rng); // Remove one participant from the contexts and all nested structures let mut remaining_participants = contexts.clone(); @@ -736,7 +742,7 @@ mod tests { .collect(); // Create a decryption share from a recovered private key share - let new_validator_decryption_key = Fr::rand(rng); + let new_validator_decryption_key = ScalarField::rand(rng); let validator_index = removed_participant.index; decryption_shares.push( DecryptionShareSimple::create( @@ -774,7 +780,7 @@ mod tests { setup_simple::(threshold, shares_num, rng); let g_inv = &contexts[0].setup_params.g_inv; let pub_contexts = contexts[0].public_decryption_contexts.clone(); - let ciphertext = encrypt::<_, E>(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng); // Create an initial shared secret let old_shared_secret = make_shared_secret_from_contexts( @@ -787,8 +793,11 @@ mod tests { // Now, we're going to refresh the shares and check that the shared secret is the same // Dealer computes a new random polynomial with constant term x_r - let polynomial = - make_random_polynomial_at::(threshold, &Fr::zero(), rng); + let polynomial = make_random_polynomial_at::( + threshold, + &ScalarField::zero(), + rng, + ); // Dealer shares the polynomial with participants @@ -799,7 +808,7 @@ mod tests { .map(|(i, p)| { // Participant computes share updates and update their private key shares let private_key_share = refresh_private_key_share::( - &p.setup_params.h.into_projective(), + &p.setup_params.h.into_group(), &p.public_decryption_contexts[i].domain, &polynomial, &p.private_key_share, diff --git a/tpke/src/refresh.rs b/tpke/src/refresh.rs index f80b32f5..2ef6e6c2 100644 --- a/tpke/src/refresh.rs +++ b/tpke/src/refresh.rs @@ -1,21 +1,23 @@ +use std::ops::Mul; use std::usize; -use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; -use ark_ff::{PrimeField, Zero}; -use ark_poly::{univariate::DensePolynomial, Polynomial, UVPolynomial}; +use ark_ec::pairing::Pairing; +use ark_ec::{AffineRepr, CurveGroup}; +use ark_ff::Zero; +use ark_poly::{univariate::DensePolynomial, DenseUVPolynomial, Polynomial}; use itertools::zip_eq; use rand_core::RngCore; use crate::{lagrange_basis_at, PrivateKeyShare}; /// From PSS paper, section 4.2.1, (https://link.springer.com/content/pdf/10.1007/3-540-44750-4_27.pdf) -pub fn prepare_share_updates_for_recovery( - domain_points: &[E::Fr], +pub fn prepare_share_updates_for_recovery( + domain_points: &[E::ScalarField], h: &E::G2Affine, - x_r: &E::Fr, + x_r: &E::ScalarField, threshold: usize, rng: &mut impl RngCore, -) -> Vec { +) -> Vec { // Generate a new random polynomial with constant term x_r let d_i = make_random_polynomial_at::(threshold, x_r, rng); @@ -24,20 +26,20 @@ pub fn prepare_share_updates_for_recovery( .iter() .map(|x_i| { let eval = d_i.evaluate(x_i); - h.mul(eval.into_repr()) + h.mul(eval) }) .collect() } /// From PSS paper, section 4.2.3, (https://link.springer.com/content/pdf/10.1007/3-540-44750-4_27.pdf) -pub fn update_share_for_recovery( +pub fn update_share_for_recovery( private_key_share: &PrivateKeyShare, - share_updates: &[E::G2Projective], + share_updates: &[E::G2], ) -> PrivateKeyShare { let private_key_share = share_updates .iter() .fold( - private_key_share.private_key_share.into_projective(), + private_key_share.private_key_share.into_group(), |acc, delta| acc + delta, ) .into_affine(); @@ -45,57 +47,57 @@ pub fn update_share_for_recovery( } /// From the PSS paper, section 4.2.4, (https://link.springer.com/content/pdf/10.1007/3-540-44750-4_27.pdf) -pub fn recover_share_from_updated_private_shares( - x_r: &E::Fr, - domain_points: &[E::Fr], +pub fn recover_share_from_updated_private_shares( + x_r: &E::ScalarField, + domain_points: &[E::ScalarField], updated_private_shares: &[PrivateKeyShare], ) -> PrivateKeyShare { // Interpolate new shares to recover y_r let lagrange = lagrange_basis_at::(domain_points, x_r); let prods = zip_eq(updated_private_shares, lagrange) - .map(|(y_j, l)| y_j.private_key_share.mul(l.into_repr())); - let y_r = prods.fold(E::G2Projective::zero(), |acc, y_j| acc + y_j); + .map(|(y_j, l)| y_j.private_key_share.mul(l)); + let y_r = prods.fold(E::G2::zero(), |acc, y_j| acc + y_j); PrivateKeyShare { private_key_share: y_r.into_affine(), } } -pub fn make_random_polynomial_at( +pub fn make_random_polynomial_at( threshold: usize, - root: &E::Fr, + root: &E::ScalarField, rng: &mut impl RngCore, -) -> DensePolynomial { +) -> DensePolynomial { // [][threshold-1] - let mut threshold_poly = DensePolynomial::::rand(threshold - 1, rng); + let mut threshold_poly = + DensePolynomial::::rand(threshold - 1, rng); // [0..][threshold] - threshold_poly[0] = E::Fr::zero(); + threshold_poly[0] = E::ScalarField::zero(); // Now, we calculate d_i_0 // This is the term that will "zero out" the polynomial at x_r, d_i(x_r) = 0 - let d_i_0 = E::Fr::zero() - threshold_poly.evaluate(root); + let d_i_0 = E::ScalarField::zero() - threshold_poly.evaluate(root); threshold_poly[0] = d_i_0; - debug_assert!(threshold_poly.evaluate(root) == E::Fr::zero()); + debug_assert!(threshold_poly.evaluate(root) == E::ScalarField::zero()); debug_assert!(threshold_poly.coeffs.len() == threshold); threshold_poly } // TODO: Expose a method to create a proper decryption share after refreshing -pub fn refresh_private_key_share( - h: &E::G2Projective, - domain_point: &E::Fr, - polynomial: &DensePolynomial, +pub fn refresh_private_key_share( + h: &E::G2, + domain_point: &E::ScalarField, + polynomial: &DensePolynomial, validator_private_key_share: &PrivateKeyShare, ) -> PrivateKeyShare { let evaluated_polynomial = polynomial.evaluate(domain_point); - let share_update = h.mul(evaluated_polynomial.into_repr()); - let updated_share = validator_private_key_share - .private_key_share - .into_projective() - + share_update; + let share_update = h.mul(evaluated_polynomial); + let updated_share = + validator_private_key_share.private_key_share.into_group() + + share_update; PrivateKeyShare { private_key_share: updated_share.into_affine(), } From faae4207c1663002c2f3dba10d0da627d6e72bb9 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Wed, 15 Feb 2023 11:53:13 +0100 Subject: [PATCH 21/36] fix cargo-udeps-action not working on stable --- .github/workflows/workspace.yml | 7 +++++++ rustfmt.toml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index 53ff7fab..fa695c91 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -43,6 +43,13 @@ jobs: with: command: fmt args: --all -- --check + # Switching to nightly here because cargo-udeps-action doesn't work on stable + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + components: clippy + override: true + profile: minimal - uses: aig787/cargo-udeps-action@v1 with: version: 'latest' diff --git a/rustfmt.toml b/rustfmt.toml index de81e7e3..8ad17fc5 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -6,7 +6,7 @@ use_small_heuristics = "Default" reorder_imports = true reorder_modules = true remove_nested_parens = true -fn_args_layout = "Tall" +fn_params_layout = "Tall" edition = "2018" merge_derives = true use_try_shorthand = false From eb9322bc3ff49e060b03abf8a915654f3a857f7b Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Wed, 15 Feb 2023 13:12:06 +0100 Subject: [PATCH 22/36] remove unused crate --- Cargo.lock | 30 ------------------------------ ferveo/Cargo.toml | 1 - 2 files changed, 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89ef78b8..bc6e93ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,18 +154,6 @@ dependencies = [ "rand 0.8.5", ] -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - [[package]] name = "atty" version = "0.2.14" @@ -204,17 +192,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "blake2b_simd" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] - [[package]] name = "block-buffer" version = "0.9.0" @@ -408,12 +385,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - [[package]] name = "core-foundation-sys" version = "0.8.3" @@ -754,7 +725,6 @@ dependencies = [ "ark-serialize", "ark-std", "bincode", - "blake2b_simd", "criterion 0.3.6", "digest 0.10.6", "ed25519-dalek", diff --git a/ferveo/Cargo.toml b/ferveo/Cargo.toml index 05f6628a..121bd6b5 100644 --- a/ferveo/Cargo.toml +++ b/ferveo/Cargo.toml @@ -23,7 +23,6 @@ either = "1.6.1" miracl_core = "2.3.0" ed25519-dalek = { version = "1", features = ["serde", "batch"] } serde = { version = "1.0", features = ["derive"] } -blake2b_simd = "1" zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] } serde_bytes = { version = "0.11" } bincode = "1.3" From 3040970d1d61cbb13a7577422a5422eca445deca Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Wed, 15 Feb 2023 13:53:09 +0100 Subject: [PATCH 23/36] replace unmaintained rust-crypto crate with sha2 --- Cargo.lock | 112 ++++++----------------------------------- tpke/Cargo.toml | 2 +- tpke/src/ciphertext.rs | 13 ++--- 3 files changed, 20 insertions(+), 107 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bc6e93ff..4eaf123f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -703,7 +703,7 @@ dependencies = [ "rand 0.7.3", "serde", "serde_bytes", - "sha2", + "sha2 0.9.9", "zeroize", ] @@ -777,18 +777,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - -[[package]] -name = "gcc" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" - [[package]] name = "generic-array" version = "0.14.6" @@ -844,9 +832,9 @@ dependencies = [ "rand 0.8.5", "rand_core 0.6.4", "rayon", - "rust-crypto", "serde", "serde_with", + "sha2 0.10.6", "subproductdomain", "thiserror", ] @@ -1319,29 +1307,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" -dependencies = [ - "libc", - "rand 0.4.6", -] - -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", -] - [[package]] name = "rand" version = "0.7.3" @@ -1386,21 +1351,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.5.1" @@ -1451,15 +1401,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_syscall" version = "0.2.16" @@ -1490,25 +1431,6 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" -[[package]] -name = "rust-crypto" -version = "0.2.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" -dependencies = [ - "gcc", - "libc", - "rand 0.3.23", - "rustc-serialize", - "time 0.1.44", -] - -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" - [[package]] name = "rustc_version" version = "0.3.3" @@ -1632,7 +1554,7 @@ dependencies = [ "serde", "serde_json", "serde_with_macros", - "time 0.3.17", + "time", ] [[package]] @@ -1660,6 +1582,17 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.6", +] + [[package]] name = "signature" version = "1.6.4" @@ -1770,17 +1703,6 @@ dependencies = [ "syn", ] -[[package]] -name = "time" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.3.17" @@ -1918,12 +1840,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/tpke/Cargo.toml b/tpke/Cargo.toml index 48d8585b..748791cc 100644 --- a/tpke/Cargo.toml +++ b/tpke/Cargo.toml @@ -21,7 +21,6 @@ rand = "0.8" rayon = "1.5" thiserror = "=1.0.30" anyhow = "=1.0" -rust-crypto = "0.2.36" miracl_core = "=2.3.0" ark-ff = "0.3" ark-ec = "0.3" @@ -36,6 +35,7 @@ chacha20poly1305 = "0.10.1" serde = { version = "1.0", features = ["derive"] } serde_with = "2.0.1" bincode = "1.3.3" +sha2 = "0.10.6" [dev-dependencies] criterion = { version = "0.4", features = ["html_reports"] } diff --git a/tpke/src/ciphertext.rs b/tpke/src/ciphertext.rs index 1baf4bef..e9a24a13 100644 --- a/tpke/src/ciphertext.rs +++ b/tpke/src/ciphertext.rs @@ -5,10 +5,10 @@ use chacha20poly1305::{ aead::{generic_array::GenericArray, Aead, KeyInit}, ChaCha20Poly1305, Nonce, }; -use crypto::{digest::Digest, sha2::Sha256}; use rand_core::RngCore; use serde::{Deserialize, Serialize}; use serde_with::serde_as; +use sha2::{digest::Digest, Sha256}; use crate::serialization; use crate::{htp_bls12381_g2, Result, ThresholdEncryptionError}; @@ -17,11 +17,9 @@ use crate::{htp_bls12381_g2, Result, ThresholdEncryptionError}; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Ciphertext { #[serde_as(as = "serialization::SerdeAs")] - pub commitment: E::G1Affine, - // U + pub commitment: E::G1Affine, // U #[serde_as(as = "serialization::SerdeAs")] - pub auth_tag: E::G2Affine, - // W + pub auth_tag: E::G2Affine, // W pub ciphertext: Vec, // V } @@ -161,10 +159,9 @@ pub fn decrypt_with_shared_secret( } fn sha256(input: &[u8]) -> Vec { - let mut result = [0u8; 32]; let mut hasher = Sha256::new(); - hasher.input(input); - hasher.result(&mut result); + hasher.update(input); + let result = hasher.finalize(); result.to_vec() } From f876b85732a31970a421f1a75c54a2a17aa48e95 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Wed, 15 Feb 2023 14:42:44 +0100 Subject: [PATCH 24/36] remove unused crates --- Cargo.lock | 3 --- ferveo-common/Cargo.toml | 5 ----- 2 files changed, 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f97a443d..3ffa38a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -838,13 +838,10 @@ dependencies = [ name = "ferveo-common" version = "0.1.0" dependencies = [ - "ark-bls12-381", "ark-ec", "ark-serialize", "ark-std", - "bincode", "serde", - "serde_json", "serde_with", ] diff --git a/ferveo-common/Cargo.toml b/ferveo-common/Cargo.toml index 873b0f18..d3218f3c 100644 --- a/ferveo-common/Cargo.toml +++ b/ferveo-common/Cargo.toml @@ -12,11 +12,6 @@ serde = { version = "1.0", features = ["derive"] } ark-serialize = {version = "0.4", features = ["derive"]} serde_with = "2.2.0" -[dev-dependencies] -ark-bls12-381 = "0.4" -serde_json = "1.0" -bincode = "1.0" - [profile.release] opt-level = 3 lto = true From 2d926de9a96a9492063fe4ad69a4dee51d5cae88 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Wed, 15 Feb 2023 15:33:25 +0100 Subject: [PATCH 25/36] self review --- Cargo.lock | 1 + ferveo/src/dkg.rs | 1 - subproductdomain/src/lib.rs | 5 +++-- tpke/Cargo.toml | 1 + tpke/src/ciphertext.rs | 2 +- tpke/src/decryption.rs | 4 ---- tpke/src/key_share.rs | 7 ++----- 7 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3ffa38a6..55f92634 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -936,6 +936,7 @@ dependencies = [ "rand 0.8.5", "rand_core 0.6.4", "serde", + "serde_bytes", "serde_with", "sha2 0.10.6", "subproductdomain", diff --git a/ferveo/src/dkg.rs b/ferveo/src/dkg.rs index c76a5d09..32cdf933 100644 --- a/ferveo/src/dkg.rs +++ b/ferveo/src/dkg.rs @@ -24,7 +24,6 @@ pub use pv::*; // DKG parameters #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct Params { - // TODO: Rename to ritual_id? pub tau: u64, pub security_threshold: u32, pub shares_num: u32, diff --git a/subproductdomain/src/lib.rs b/subproductdomain/src/lib.rs index e3538312..723b4ed7 100644 --- a/subproductdomain/src/lib.rs +++ b/subproductdomain/src/lib.rs @@ -1,6 +1,8 @@ #![allow(non_snake_case)] #![allow(dead_code)] +use std::mem; + use ark_ec::pairing::Pairing; use ark_ec::scalar_mul::fixed_base::FixedBase; use ark_ec::AffineRepr; @@ -20,8 +22,7 @@ pub fn fast_multiexp( ) -> Vec { let window_size = FixedBase::get_mul_window_size(scalars.len()); - // let scalar_bits = mem::size_of::(); - let scalar_bits: usize = 255; // TODO: How to get this from the scalar field? + let scalar_bits: usize = mem::size_of::() * 8 - 1; let base_table = FixedBase::get_window_table(scalar_bits, window_size, base); diff --git a/tpke/Cargo.toml b/tpke/Cargo.toml index 554b8d32..ed7ff069 100644 --- a/tpke/Cargo.toml +++ b/tpke/Cargo.toml @@ -34,6 +34,7 @@ serde = { version = "1.0", features = ["derive"] } serde_with = "2.0.1" bincode = "1.3.3" sha2 = "0.10.6" +serde_bytes = "0.11.9" [dev-dependencies] criterion = { version = "0.4", features = ["html_reports"] } diff --git a/tpke/src/ciphertext.rs b/tpke/src/ciphertext.rs index 5a5f1287..60b5f0a0 100644 --- a/tpke/src/ciphertext.rs +++ b/tpke/src/ciphertext.rs @@ -22,7 +22,7 @@ pub struct Ciphertext { pub commitment: E::G1Affine, // U #[serde_as(as = "serialization::SerdeAs")] pub auth_tag: E::G2Affine, // W - // #[serde(with = "serde_bytes")] // TODO: Consider using serde_bytes for raw bytes + #[serde(with = "serde_bytes")] pub ciphertext: Vec, // V } diff --git a/tpke/src/decryption.rs b/tpke/src/decryption.rs index 45cc909d..bd51cbf6 100644 --- a/tpke/src/decryption.rs +++ b/tpke/src/decryption.rs @@ -1,4 +1,3 @@ -use std::marker::PhantomData; use std::ops::Mul; use anyhow::Result; @@ -98,7 +97,6 @@ pub struct DecryptionShareSimple { #[serde_as(as = "serialization::SerdeAs")] pub decryption_share: E::TargetField, pub validator_checksum: ValidatorShareChecksum, - phantom2: PhantomData, } impl DecryptionShareSimple { @@ -143,10 +141,8 @@ impl DecryptionShareSimple { decrypter_index: validator_index, decryption_share, validator_checksum, - phantom2: PhantomData, } } - /// Verify that the decryption share is valid. pub fn verify( &self, diff --git a/tpke/src/key_share.rs b/tpke/src/key_share.rs index 52354348..e0289689 100644 --- a/tpke/src/key_share.rs +++ b/tpke/src/key_share.rs @@ -13,11 +13,8 @@ pub struct PublicKeyShare { #[derive(Debug, Clone)] pub struct BlindedKeyShare { - pub blinding_key: E::G2Affine, - // [b] H - pub blinded_key_share: E::G2Affine, - // [b] Z_{i, \omega_i} - // TODO: Should we use this kind of optizmization here or anywhere else? + pub blinding_key: E::G2Affine, // [b] H + pub blinded_key_share: E::G2Affine, // [b] Z_{i, \omega_i} pub blinding_key_prepared: E::G2Prepared, } From a9b4331c3755a0bb0dc0ca5cc355a892dc13d7d3 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Wed, 15 Feb 2023 20:57:13 +0100 Subject: [PATCH 26/36] replace unwrap calls with result type --- Cargo.lock | 2 + ferveo-common/Cargo.toml | 1 + ferveo-common/src/keypair.rs | 18 ++++++ ferveo-python/src/lib.rs | 108 ++++++++++++++++++-------------- ferveo/src/api.rs | 115 +++++++++++++---------------------- ferveo/src/lib.rs | 16 +++-- ferveo/src/vss/pvss.rs | 4 +- tpke-python/src/lib.rs | 7 ++- tpke-wasm/Cargo.toml | 1 + tpke-wasm/src/lib.rs | 71 ++++++++++++--------- tpke-wasm/src/utils.rs | 8 +++ tpke-wasm/tests/node.rs | 22 +++---- tpke/benches/tpke.rs | 19 +++--- tpke/src/api.rs | 24 ++++---- tpke/src/ciphertext.rs | 90 ++++++++++++++------------- tpke/src/decryption.rs | 67 +++++++++++--------- tpke/src/lib.rs | 37 +++++++---- 17 files changed, 343 insertions(+), 267 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 55f92634..c560ee11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -841,6 +841,7 @@ dependencies = [ "ark-ec", "ark-serialize", "ark-std", + "bincode", "serde", "serde_with", ] @@ -2059,6 +2060,7 @@ dependencies = [ "ferveo-common", "getrandom 0.2.8", "group-threshold-cryptography", + "js-sys", "rand 0.8.5", "rand_core 0.6.4", "serde", diff --git a/ferveo-common/Cargo.toml b/ferveo-common/Cargo.toml index d3218f3c..775c03b0 100644 --- a/ferveo-common/Cargo.toml +++ b/ferveo-common/Cargo.toml @@ -11,6 +11,7 @@ ark-ec = "0.4" serde = { version = "1.0", features = ["derive"] } ark-serialize = {version = "0.4", features = ["derive"]} serde_with = "2.2.0" +bincode = "1.3.3" [profile.release] opt-level = 3 diff --git a/ferveo-common/src/keypair.rs b/ferveo-common/src/keypair.rs index 756eccee..d30bcb74 100644 --- a/ferveo-common/src/keypair.rs +++ b/ferveo-common/src/keypair.rs @@ -36,6 +36,16 @@ impl Default for PublicKey { } } +impl PublicKey { + pub fn to_bytes(&self) -> Result, bincode::Error> { + bincode::serialize(&self) + } + + pub fn from_bytes(bytes: &[u8]) -> Result { + bincode::deserialize(bytes) + } +} + #[serde_as] #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct Keypair { @@ -60,4 +70,12 @@ impl Keypair { decryption_key: E::ScalarField::rand(rng), } } + + pub fn to_bytes(&self) -> Result, bincode::Error> { + bincode::serialize(&self) + } + + pub fn from_bytes(bytes: &[u8]) -> Result { + bincode::deserialize(bytes) + } } diff --git a/ferveo-python/src/lib.rs b/ferveo-python/src/lib.rs index d1d3c836..01b61180 100644 --- a/ferveo-python/src/lib.rs +++ b/ferveo-python/src/lib.rs @@ -1,5 +1,7 @@ extern crate alloc; +use ferveo::api::E; +use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::types::PyBytes; use rand::thread_rng; @@ -9,8 +11,10 @@ pub fn encrypt( message: &[u8], aad: &[u8], public_key: &DkgPublicKey, -) -> Ciphertext { - Ciphertext(ferveo::api::encrypt(message, aad, &public_key.0)) +) -> PyResult { + let ciphertext = ferveo::api::encrypt(message, aad, &public_key.0) + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + Ok(Ciphertext(ciphertext)) } #[pyfunction] @@ -28,13 +32,14 @@ pub fn decrypt_with_shared_secret( aad: &[u8], shared_secret: &SharedSecret, g1_inv: &G1Prepared, -) -> Vec { +) -> PyResult> { ferveo::api::decrypt_with_shared_secret( &ciphertext.0, aad, &shared_secret.0, &g1_inv.0, ) + .map_err(|err| PyValueError::new_err(format!("{}", err))) } #[pyclass(module = "ferveo")] @@ -47,45 +52,55 @@ pub struct SharedSecret(ferveo::api::SharedSecret); #[pyclass(module = "ferveo")] #[derive(derive_more::From, derive_more::AsRef)] -pub struct Keypair(ferveo::api::Keypair); +pub struct Keypair(ferveo::api::Keypair); #[pymethods] impl Keypair { #[staticmethod] pub fn random() -> Self { - Self(ferveo::api::Keypair::random(&mut thread_rng())) + Self(ferveo::api::Keypair::new(&mut thread_rng())) } #[staticmethod] - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(ferveo::api::Keypair::from_bytes(bytes)) + pub fn from_bytes(bytes: &[u8]) -> PyResult { + let keypair = ferveo::api::Keypair::from_bytes(bytes) + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + Ok(Self(keypair)) } - fn __bytes__(&self) -> PyObject { - let serialized = self.0.to_bytes(); - Python::with_gil(|py| PyBytes::new(py, &serialized).into()) + fn __bytes__(&self) -> PyResult { + let serialized = self + .0 + .to_bytes() + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + Python::with_gil(|py| Ok(PyBytes::new(py, &serialized).into())) } #[getter] pub fn public_key(&self) -> PublicKey { - PublicKey(self.0.public_key()) + PublicKey(self.0.public()) } } #[pyclass(module = "ferveo")] #[derive(Clone, derive_more::From, derive_more::AsRef)] -pub struct PublicKey(ferveo::api::PublicKey); +pub struct PublicKey(ferveo::api::PublicKey); #[pymethods] impl PublicKey { #[staticmethod] - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(ferveo::api::PublicKey::from_bytes(bytes)) + pub fn from_bytes(bytes: &[u8]) -> PyResult { + let pk = ferveo::api::PublicKey::from_bytes(bytes) + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + Ok(Self(pk)) } - fn __bytes__(&self) -> PyObject { - let serialized = self.0.to_bytes(); - Python::with_gil(|py| PyBytes::new(py, &serialized).into()) + fn __bytes__(&self) -> PyResult { + let serialized = self + .0 + .to_bytes() + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + Python::with_gil(|py| Ok(PyBytes::new(py, &serialized).into())) } } @@ -108,13 +123,18 @@ pub struct Transcript(ferveo::api::Transcript); #[pymethods] impl Transcript { #[staticmethod] - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(ferveo::api::Transcript::from_bytes(bytes)) + pub fn from_bytes(bytes: &[u8]) -> PyResult { + let transcript = ferveo::api::Transcript::from_bytes(bytes) + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + Ok(Self(transcript)) } - fn __bytes__(&self) -> PyObject { - let serialized = self.0.to_bytes(); - Python::with_gil(|py| PyBytes::new(py, &serialized).into()) + fn __bytes__(&self) -> PyResult { + let serialized = self + .0 + .to_bytes() + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + Ok(Python::with_gil(|py| PyBytes::new(py, &serialized).into())) } } @@ -138,15 +158,17 @@ impl Dkg { security_threshold: u32, validators: Vec, me: ExternalValidator, - ) -> Self { + ) -> PyResult { let validators: Vec<_> = validators.into_iter().map(|v| v.0).collect(); - Self(ferveo::api::Dkg::new( + let dkg = ferveo::api::Dkg::new( tau, shares_num, security_threshold, &validators, &me.0, - )) + ) + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + Ok(Self(dkg)) } #[getter] @@ -154,21 +176,13 @@ impl Dkg { DkgPublicKey(self.0.final_key()) } - pub fn generate_transcript(&self) -> Transcript { + pub fn generate_transcript(&self) -> PyResult { let rng = &mut thread_rng(); - Transcript(self.0.generate_transcript(rng)) - } - - pub fn aggregate_transcripts( - // TODO: Avoid mutating current state - &mut self, - messages: Vec, - ) -> AggregatedTranscript { - let messages = &messages - .into_iter() - .map(|message| (message.0 .0, message.1 .0)) - .collect(); - AggregatedTranscript(self.0.aggregate_transcripts(messages)) + let transcript = self + .0 + .generate_transcript(rng) + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + Ok(Transcript(transcript)) } } @@ -210,13 +224,19 @@ impl AggregatedTranscript { } #[staticmethod] - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(ferveo::api::AggregatedTranscript::from_bytes(bytes)) + pub fn from_bytes(bytes: &[u8]) -> PyResult { + let aggregated_transcript = + ferveo::api::AggregatedTranscript::from_bytes(bytes) + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + Ok(Self(aggregated_transcript)) } - fn __bytes__(&self) -> PyObject { - let serialized = self.0.to_bytes(); - Python::with_gil(|py| PyBytes::new(py, &serialized).into()) + fn __bytes__(&self) -> PyResult { + let serialized = self + .0 + .to_bytes() + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + Ok(Python::with_gil(|py| PyBytes::new(py, &serialized).into())) } } diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index 4987156b..11cb8c40 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -2,7 +2,9 @@ use ark_poly::EvaluationDomain; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use bincode::Options; use ferveo_common::serialization::ser::serialize; +pub use ferveo_common::{Keypair, PublicKey}; use group_threshold_cryptography as tpke; +use group_threshold_cryptography::api::TpkeResult; use rand::rngs::StdRng; use rand::{thread_rng, RngCore, SeedableRng}; use serde::{Deserialize, Serialize}; @@ -13,8 +15,8 @@ pub fn encrypt( message: &[u8], aad: &[u8], public_key: &DkgPublicKey, -) -> Ciphertext { - Ciphertext(tpke::api::encrypt(message, aad, &public_key.0)) +) -> TpkeResult { + Ok(Ciphertext(tpke::api::encrypt(message, aad, &public_key.0)?)) } pub fn combine_decryption_shares( @@ -32,61 +34,27 @@ pub fn decrypt_with_shared_secret( aad: &[u8], shared_secret: &SharedSecret, g_inv: &G1Prepared, -) -> Vec { +) -> TpkeResult> { tpke::api::decrypt_with_shared_secret( &ciphertext.0, aad, &shared_secret.0, &g_inv.0, ) - .unwrap() } + pub struct G1Prepared(pub tpke::api::TpkeG1Prepared); pub struct SharedSecret(tpke::api::TpkeSharedSecret); -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Keypair(ferveo_common::Keypair); - -impl Keypair { - pub fn random(rng: &mut R) -> Self { - Self(ferveo_common::Keypair::::new(rng)) - } - - pub fn public_key(&self) -> PublicKey { - PublicKey(self.0.public()) - } - - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(bincode::deserialize(bytes).unwrap()) - } - - pub fn to_bytes(&self) -> Vec { - bincode::serialize(&self.0).unwrap() - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct PublicKey(ferveo_common::PublicKey); - -impl PublicKey { - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(bincode::deserialize(bytes).unwrap()) - } - - pub fn to_bytes(&self) -> Vec { - bincode::serialize(&self.0).unwrap() - } -} - #[derive(Clone)] pub struct ExternalValidator(ferveo_common::ExternalValidator); impl ExternalValidator { - pub fn new(address: String, public_key: PublicKey) -> Self { + pub fn new(address: String, public_key: PublicKey) -> Self { Self(ferveo_common::ExternalValidator { address, - public_key: public_key.0, + public_key, }) } } @@ -95,12 +63,12 @@ impl ExternalValidator { pub struct Transcript(crate::PubliclyVerifiableSS); impl Transcript { - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(bincode::deserialize(bytes).unwrap()) + pub fn from_bytes(bytes: &[u8]) -> Result { + Ok(Self(bincode::deserialize(bytes)?)) } - pub fn to_bytes(&self) -> Vec { - bincode::serialize(&self.0).unwrap() + pub fn to_bytes(&self) -> Result, crate::Error> { + Ok(bincode::serialize(&self.0)?) } } @@ -117,7 +85,7 @@ impl Dkg { security_threshold: u32, validators: &[ExternalValidator], me: &ExternalValidator, - ) -> Self { + ) -> Result { let validators = &validators .iter() .map(|v| v.0.clone()) @@ -128,7 +96,7 @@ impl Dkg { security_threshold, shares_num, }; - let session_keypair = ferveo_common::Keypair:: { + let session_keypair = Keypair:: { decryption_key: ark_ff::UniformRand::rand(&mut ark_std::test_rng()), }; let dkg = crate::PubliclyVerifiableDkg::::new( @@ -136,32 +104,31 @@ impl Dkg { params, me, session_keypair, - ) - .unwrap(); - Self(dkg) + )?; + Ok(Self(dkg)) } pub fn final_key(&self) -> DkgPublicKey { DkgPublicKey(self.0.final_key()) } - pub fn generate_transcript(&self, rng: &mut R) -> Transcript { - Transcript(self.0.create_share(rng).unwrap()) + pub fn generate_transcript( + &self, + rng: &mut R, + ) -> Result { + Ok(Transcript(self.0.create_share(rng)?)) } pub fn aggregate_transcripts( &mut self, messages: &Vec<(ExternalValidator, Transcript)>, - ) -> AggregatedTranscript { + ) -> Result { // Avoid mutating current state // TODO: Rewrite `deal` to not require mutability after validating this API design for (validator, transcript) in messages { - self.0 - .deal(validator.0.clone(), transcript.0.clone()) - .unwrap(); + self.0.deal(validator.0.clone(), transcript.0.clone())?; } - - AggregatedTranscript(crate::pvss::aggregate(&self.0)) + Ok(AggregatedTranscript(crate::pvss::aggregate(&self.0))) } } @@ -187,25 +154,25 @@ impl AggregatedTranscript { dkg: &Dkg, ciphertext: &Ciphertext, aad: &[u8], - validator_keypair: &Keypair, + validator_keypair: &Keypair, ) -> DecryptionShare { let domain_points: Vec<_> = dkg.0.domain.elements().collect(); DecryptionShare(self.0.make_decryption_share_simple_precomputed( &ciphertext.0 .0, aad, - &validator_keypair.0.decryption_key, + &validator_keypair.decryption_key, dkg.0.me, &domain_points, &dkg.0.pvss_params.g_inv(), )) } - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(bincode::deserialize(bytes).unwrap()) + pub fn from_bytes(bytes: &[u8]) -> Result { + Ok(Self(bincode::deserialize(bytes)?)) } - pub fn to_bytes(&self) -> Vec { - bincode::serialize(&self.0).unwrap() + pub fn to_bytes(&self) -> Result, crate::Error> { + Ok(bincode::serialize(&self.0)?) } } @@ -259,8 +226,9 @@ mod test_ferveo_api { security_threshold, &validators, sender, - ); - (sender.clone(), dkg.generate_transcript(rng)) + ) + .unwrap(); + (sender.clone(), dkg.generate_transcript(rng).unwrap()) }) .collect(); @@ -268,8 +236,9 @@ mod test_ferveo_api { // every validator can aggregate the transcripts let me = validators[0].clone(); let mut dkg = - Dkg::new(tau, shares_num, security_threshold, &validators, &me); - let pvss_aggregated = dkg.aggregate_transcripts(&messages); + Dkg::new(tau, shares_num, security_threshold, &validators, &me) + .unwrap(); + let pvss_aggregated = dkg.aggregate_transcripts(&messages).unwrap(); // At this point, any given validator should be able to provide a DKG public key let public_key = dkg.final_key(); @@ -277,7 +246,7 @@ mod test_ferveo_api { // In the meantime, the client creates a ciphertext and decryption request let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); - let ciphertext = encrypt(msg, aad, &public_key); + let ciphertext = encrypt(msg, aad, &public_key).unwrap(); // Having aggregated the transcripts, the validators can now create decryption shares let decryption_shares: Vec<_> = izip!(&validators, &validator_keypairs) @@ -289,14 +258,15 @@ mod test_ferveo_api { security_threshold, &validators, validator, - ); - let aggregate = dkg.aggregate_transcripts(&messages); + ) + .unwrap(); + let aggregate = dkg.aggregate_transcripts(&messages).unwrap(); assert!(pvss_aggregated.validate(&dkg)); aggregate.create_decryption_share( &dkg, &ciphertext, aad, - &Keypair(*validator_keypair), + validator_keypair, ) }) .collect(); @@ -311,7 +281,8 @@ mod test_ferveo_api { aad, &shared_secret, &G1Prepared(dkg.0.pvss_params.g_inv()), - ); + ) + .unwrap(); assert_eq!(plaintext, msg); } } diff --git a/ferveo/src/lib.rs b/ferveo/src/lib.rs index 88843bb0..acecf949 100644 --- a/ferveo/src/lib.rs +++ b/ferveo/src/lib.rs @@ -5,6 +5,7 @@ pub mod dkg; pub mod primitives; mod vss; +pub use anyhow::Error; pub use dkg::*; pub use primitives::*; pub use vss::*; @@ -105,7 +106,8 @@ mod test_dkg_full { let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); let public_key = dkg.final_key(); - let ciphertext = tpke::encrypt::(msg, aad, &public_key, rng); + let ciphertext = + tpke::encrypt::(msg, aad, &public_key, rng).unwrap(); let validator_keypairs = gen_n_keypairs(4); let (_, _, shared_secret) = make_shared_secret_simple_tdec( @@ -133,8 +135,8 @@ mod test_dkg_full { let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); let public_key = dkg.final_key(); - let ciphertext = tpke::encrypt::(msg, aad, &public_key, rng); - let _g_inv = dkg.pvss_params.g_inv(); + let ciphertext = + tpke::encrypt::(msg, aad, &public_key, rng).unwrap(); let validator_keypairs = gen_n_keypairs(4); let pvss_aggregated = aggregate(&dkg); @@ -182,7 +184,8 @@ mod test_dkg_full { let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); let public_key = dkg.final_key(); - let ciphertext = tpke::encrypt::(msg, aad, &public_key, rng); + let ciphertext = + tpke::encrypt::(msg, aad, &public_key, rng).unwrap(); let validator_keypairs = gen_n_keypairs(4); let (pvss_aggregated, decryption_shares, _) = @@ -241,7 +244,7 @@ mod test_dkg_full { let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); let public_key = &dkg.final_key(); - let ciphertext = tpke::encrypt::(msg, aad, public_key, rng); + let ciphertext = tpke::encrypt::(msg, aad, public_key, rng).unwrap(); let mut validator_keypairs = gen_n_keypairs(4); // Create an initial shared secret @@ -357,7 +360,8 @@ mod test_dkg_full { let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); let public_key = dkg.final_key(); - let ciphertext = tpke::encrypt::(msg, aad, &public_key, rng); + let ciphertext = + tpke::encrypt::(msg, aad, &public_key, rng).unwrap(); let validator_keypairs = gen_n_keypairs(4); let pvss_aggregated = aggregate(&dkg); diff --git a/ferveo/src/vss/pvss.rs b/ferveo/src/vss/pvss.rs index c757e4bb..43382005 100644 --- a/ferveo/src/vss/pvss.rs +++ b/ferveo/src/vss/pvss.rs @@ -345,7 +345,9 @@ pub fn aggregate( ) -> PubliclyVerifiableSS { let pvss = &dkg.vss; let mut pvss_iter = pvss.iter(); - let (_, first_pvss) = pvss_iter.next().unwrap(); + let (_, first_pvss) = pvss_iter + .next() + .expect("May not aggregate empty PVSS instances"); let mut coeffs = batch_to_projective_g1::(&first_pvss.coeffs); let mut sigma = first_pvss.sigma; diff --git a/tpke-python/src/lib.rs b/tpke-python/src/lib.rs index 0cfef787..7b270b8d 100644 --- a/tpke-python/src/lib.rs +++ b/tpke-python/src/lib.rs @@ -2,6 +2,7 @@ extern crate alloc; extern crate group_threshold_cryptography as tpke; +use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::types::PyBytes; @@ -10,8 +11,12 @@ pub struct DecryptionShare(tpke::api::DecryptionShareSimplePrecomputed); impl DecryptionShare { pub fn to_bytes(&self) -> PyResult { + let bytes = self + .0 + .to_bytes() + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; Ok(Python::with_gil(|py| -> PyObject { - PyBytes::new(py, &self.0.to_bytes()).into() + PyBytes::new(py, &bytes).into() })) } } diff --git a/tpke-wasm/Cargo.toml b/tpke-wasm/Cargo.toml index 6f65f389..0ae2b59f 100644 --- a/tpke-wasm/Cargo.toml +++ b/tpke-wasm/Cargo.toml @@ -31,6 +31,7 @@ ark-serialize = { version = "0.4", features = ["derive"] } ark-ec = "0.4" ark-std = "0.4" rand_core = "0.6" +js-sys = "0.3.61" [dev-dependencies] wasm-bindgen-test = "0.3.13" diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index 715cbe18..07259cd4 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -3,6 +3,7 @@ extern crate group_threshold_cryptography as tpke; mod utils; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use js_sys::Error; use serde::{Deserialize, Serialize}; use serde_with::serde_as; use utils::*; @@ -21,13 +22,16 @@ pub struct DecryptionShareSimple(tpke::api::DecryptionShareSimple); #[wasm_bindgen] impl DecryptionShareSimple { #[wasm_bindgen] - pub fn to_bytes(&self) -> Vec { - self.0.to_bytes() + pub fn to_bytes(&self) -> Result, Error> { + self.0.to_bytes().map_err(map_js_err) } #[wasm_bindgen] - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(tpke::api::DecryptionShareSimple::from_bytes(bytes)) + pub fn from_bytes(bytes: &[u8]) -> Result { + let decryption_shares = + tpke::api::DecryptionShareSimple::from_bytes(bytes) + .map_err(map_js_err)?; + Ok(Self(decryption_shares)) } } @@ -40,15 +44,18 @@ pub struct DecryptionShareSimplePrecomputed( #[wasm_bindgen] impl DecryptionShareSimplePrecomputed { #[wasm_bindgen] - pub fn to_bytes(&self) -> Vec { - self.0.to_bytes() + pub fn to_bytes(&self) -> Result, Error> { + self.0.to_bytes().map_err(map_js_err) } #[wasm_bindgen] - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(tpke::api::DecryptionShareSimplePrecomputed::from_bytes( - bytes, - )) + pub fn from_bytes( + bytes: &[u8], + ) -> Result { + let decryption_share = + tpke::api::DecryptionShareSimplePrecomputed::from_bytes(bytes) + .map_err(map_js_err)?; + Ok(Self(decryption_share)) } } @@ -63,19 +70,21 @@ pub struct PublicKey( #[wasm_bindgen] impl PublicKey { #[wasm_bindgen] - pub fn from_bytes(bytes: &[u8]) -> Self { + pub fn from_bytes(bytes: &[u8]) -> Result { let mut reader = bytes; let pk = tpke::api::TpkeDkgPublicKey::deserialize_uncompressed(&mut reader) - .unwrap(); - PublicKey(pk) + .map_err(map_js_err)?; + Ok(PublicKey(pk)) } #[wasm_bindgen] - pub fn to_bytes(&self) -> Vec { + pub fn to_bytes(&self) -> Result, Error> { let mut bytes = Vec::new(); - self.0.serialize_uncompressed(&mut bytes).unwrap(); - bytes + self.0 + .serialize_uncompressed(&mut bytes) + .map_err(map_js_err)?; + Ok(bytes) } } @@ -90,19 +99,21 @@ pub struct PrivateKey( #[wasm_bindgen] impl PrivateKey { #[wasm_bindgen] - pub fn from_bytes(bytes: &[u8]) -> Self { + pub fn from_bytes(bytes: &[u8]) -> Result { let mut reader = bytes; let pk = tpke::api::TpkePrivateKey::deserialize_uncompressed(&mut reader) - .unwrap(); - PrivateKey(pk) + .map_err(map_js_err)?; + Ok(PrivateKey(pk)) } #[wasm_bindgen] - pub fn to_bytes(&self) -> Vec { + pub fn to_bytes(&self) -> Result, Error> { let mut bytes = Vec::new(); - self.0.serialize_uncompressed(&mut bytes).unwrap(); - bytes + self.0 + .serialize_uncompressed(&mut bytes) + .map_err(map_js_err)?; + Ok(bytes) } } @@ -112,12 +123,14 @@ pub struct Ciphertext(tpke::api::Ciphertext); #[wasm_bindgen] impl Ciphertext { - pub fn from_bytes(bytes: &[u8]) -> Self { - Ciphertext(tpke::api::Ciphertext::from_bytes(bytes)) + pub fn from_bytes(bytes: &[u8]) -> Result { + let ciphertext = + tpke::api::Ciphertext::from_bytes(bytes).map_err(map_js_err)?; + Ok(Ciphertext(ciphertext)) } - pub fn to_bytes(&self) -> Vec { - self.0.to_bytes() + pub fn to_bytes(&self) -> Result, Error> { + self.0.to_bytes().map_err(map_js_err) } } @@ -126,9 +139,11 @@ pub fn encrypt( message: &[u8], aad: &[u8], public_key: &PublicKey, -) -> Ciphertext { +) -> Result { set_panic_hook(); - Ciphertext(tpke::api::encrypt(message, aad, &public_key.0)) + let ciphertext = + tpke::api::encrypt(message, aad, &public_key.0).map_err(map_js_err)?; + Ok(Ciphertext(ciphertext)) } #[wasm_bindgen] diff --git a/tpke-wasm/src/utils.rs b/tpke-wasm/src/utils.rs index b1d7929d..1292d393 100644 --- a/tpke-wasm/src/utils.rs +++ b/tpke-wasm/src/utils.rs @@ -1,3 +1,7 @@ +use core::fmt; + +use js_sys::Error; + pub fn set_panic_hook() { // When the `console_error_panic_hook` feature is enabled, we can call the // `set_panic_hook` function at least once during initialization, and then @@ -8,3 +12,7 @@ pub fn set_panic_hook() { #[cfg(feature = "console_error_panic_hook")] console_error_panic_hook::set_once(); } + +pub fn map_js_err(err: T) -> Error { + Error::new(&format!("{}", err)) +} diff --git a/tpke-wasm/tests/node.rs b/tpke-wasm/tests/node.rs index bb1b532e..99a57fdc 100644 --- a/tpke-wasm/tests/node.rs +++ b/tpke-wasm/tests/node.rs @@ -22,16 +22,16 @@ fn tdec_simple() { // // Encrypt the message - let ciphertext = encrypt(&msg, &aad, &dkg.public_key); + let ciphertext = encrypt(&msg, &aad, &dkg.public_key).unwrap(); // Serialize and send to validators - let ciphertext_bytes = ciphertext.to_bytes(); + let ciphertext_bytes = ciphertext.to_bytes().unwrap(); // // On the server side // - let ciphertext2 = Ciphertext::from_bytes(&ciphertext_bytes); + let ciphertext2 = Ciphertext::from_bytes(&ciphertext_bytes).unwrap(); assert_eq!(ciphertext, ciphertext2); // Create decryption shares @@ -47,7 +47,7 @@ fn tdec_simple() { // Serialize and send back to client let decryption_shares_bytes = decryption_shares .iter() - .map(|s| s.to_bytes()) + .map(|s| s.to_bytes().unwrap()) .collect::>>(); // @@ -57,7 +57,7 @@ fn tdec_simple() { let decryption_shares_2: Vec = decryption_shares_bytes .iter() - .map(|s| DecryptionShareSimple::from_bytes(s)) + .map(|s| DecryptionShareSimple::from_bytes(s).unwrap()) .collect(); assert_eq!(decryption_shares, decryption_shares_2); @@ -98,16 +98,16 @@ fn tdec_simple_precomputed() { // // Encrypt the message - let ciphertext = encrypt(&msg, &aad, &dkg_pk); + let ciphertext = encrypt(&msg, &aad, &dkg_pk).unwrap(); // Serialize and send to validators - let ciphertext_bytes = ciphertext.to_bytes(); + let ciphertext_bytes = ciphertext.to_bytes().unwrap(); // // On the server side // - let ciphertext2 = Ciphertext::from_bytes(&ciphertext_bytes); + let ciphertext2 = Ciphertext::from_bytes(&ciphertext_bytes).unwrap(); assert_eq!(ciphertext, ciphertext2); // Create decryption shares @@ -122,7 +122,7 @@ fn tdec_simple_precomputed() { // Serialize and send back to client let decryption_shares_bytes = decryption_shares .iter() - .map(|s| s.to_bytes()) + .map(|s| s.to_bytes().unwrap()) .collect::>>(); // @@ -132,7 +132,7 @@ fn tdec_simple_precomputed() { let decryption_shares_2: Vec = decryption_shares_bytes .iter() - .map(|s| DecryptionShareSimplePrecomputed::from_bytes(s)) + .map(|s| DecryptionShareSimplePrecomputed::from_bytes(s).unwrap()) .collect(); assert_eq!(decryption_shares, decryption_shares_2); @@ -164,7 +164,7 @@ fn encrypts_and_decrypts() { let dkg = Dkg::new(threshold, shares_num); - let ciphertext = encrypt(&message, &aad, &dkg.public_key); + let ciphertext = encrypt(&message, &aad, &dkg.public_key).unwrap(); let plaintext = decrypt_with_private_key( &ciphertext, &aad, diff --git a/tpke/benches/tpke.rs b/tpke/benches/tpke.rs index e57eb07f..d3373726 100644 --- a/tpke/benches/tpke.rs +++ b/tpke/benches/tpke.rs @@ -50,7 +50,7 @@ impl SetupFast { let (pubkey, privkey, contexts) = setup_fast::(threshold, shares_num, rng); - let ciphertext = encrypt::(&msg, aad, &pubkey, rng); + let ciphertext = encrypt::(&msg, aad, &pubkey, rng).unwrap(); let mut decryption_shares: Vec> = vec![]; for context in contexts.iter() { @@ -106,7 +106,7 @@ impl SetupSimple { setup_simple::(threshold, shares_num, rng); // Ciphertext.commitment is already computed to match U - let ciphertext = encrypt::(&msg, aad, &pubkey, rng); + let ciphertext = encrypt::(&msg, aad, &pubkey, rng).unwrap(); // Creating decryption shares let decryption_shares: Vec<_> = contexts @@ -336,12 +336,15 @@ pub fn bench_share_encrypt_decrypt(c: &mut Criterion) { let mut rng = rng.clone(); let setup = SetupFast::new(shares_num, msg_size, &mut rng); move || { - black_box(encrypt::( - &setup.shared.msg, - &setup.shared.aad, - &setup.shared.pubkey, - &mut rng, - )); + black_box( + encrypt::( + &setup.shared.msg, + &setup.shared.aad, + &setup.shared.pubkey, + &mut rng, + ) + .unwrap(), + ); } }; let decrypt = { diff --git a/tpke/src/api.rs b/tpke/src/api.rs index 35137cd8..2c20b85c 100644 --- a/tpke/src/api.rs +++ b/tpke/src/api.rs @@ -29,10 +29,10 @@ pub fn encrypt( message: &[u8], aad: &[u8], public_key: &TpkeDkgPublicKey, -) -> Ciphertext { +) -> TpkeResult { // TODO: Should rng be a parameter? let rng = &mut rand::thread_rng(); - Ciphertext(crate::encrypt(message, aad, public_key, rng)) + Ok(Ciphertext(crate::encrypt(message, aad, public_key, rng)?)) } pub fn decrypt_with_shared_secret( @@ -73,12 +73,12 @@ impl DomainPoint { pub struct DecryptionShareSimple(pub TpkeDecryptionShareSimple); impl DecryptionShareSimple { - pub fn to_bytes(&self) -> Vec { + pub fn to_bytes(&self) -> TpkeResult> { self.0.to_bytes() } - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(TpkeDecryptionShareSimple::from_bytes(bytes)) + pub fn from_bytes(bytes: &[u8]) -> TpkeResult { + Ok(Self(TpkeDecryptionShareSimple::from_bytes(bytes)?)) } } @@ -88,12 +88,14 @@ pub struct DecryptionShareSimplePrecomputed( ); impl DecryptionShareSimplePrecomputed { - pub fn to_bytes(&self) -> Vec { + pub fn to_bytes(&self) -> TpkeResult> { self.0.to_bytes() } - pub fn from_bytes(bytes: &[u8]) -> Self { - Self(TpkeDecryptionShareSimplePrecomputed::from_bytes(bytes)) + pub fn from_bytes(bytes: &[u8]) -> TpkeResult { + Ok(Self(TpkeDecryptionShareSimplePrecomputed::from_bytes( + bytes, + )?)) } } @@ -101,11 +103,11 @@ impl DecryptionShareSimplePrecomputed { pub struct Ciphertext(pub TpkeCiphertext); impl Ciphertext { - pub fn from_bytes(bytes: &[u8]) -> Self { - Ciphertext(TpkeCiphertext::from_bytes(bytes)) + pub fn from_bytes(bytes: &[u8]) -> crate::Result { + Ok(Ciphertext(TpkeCiphertext::from_bytes(bytes)?)) } - pub fn to_bytes(&self) -> Vec { + pub fn to_bytes(&self) -> crate::Result> { self.0.to_bytes() } } diff --git a/tpke/src/ciphertext.rs b/tpke/src/ciphertext.rs index 60b5f0a0..7dcb9cb9 100644 --- a/tpke/src/ciphertext.rs +++ b/tpke/src/ciphertext.rs @@ -19,29 +19,29 @@ use crate::{htp_bls12381_g2, Result, ThresholdEncryptionError}; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Ciphertext { #[serde_as(as = "serialization::SerdeAs")] - pub commitment: E::G1Affine, // U + pub commitment: E::G1Affine, + // U #[serde_as(as = "serialization::SerdeAs")] - pub auth_tag: E::G2Affine, // W + pub auth_tag: E::G2Affine, + // W #[serde(with = "serde_bytes")] pub ciphertext: Vec, // V } impl Ciphertext { - pub fn check(&self, g_inv: &E::G1Prepared) -> bool { - let hash_g2 = E::G2Prepared::from(self.construct_tag_hash()); + pub fn check(&self, g_inv: &E::G1Prepared) -> Result { + let hash_g2 = E::G2Prepared::from(self.construct_tag_hash()?); - E::multi_pairing( + Ok(E::multi_pairing( [self.commitment.into(), g_inv.to_owned()], [hash_g2, self.auth_tag.into()], ) - .0 == E::TargetField::one() + .0 == E::TargetField::one()) } - fn construct_tag_hash(&self) -> E::G2Affine { + fn construct_tag_hash(&self) -> Result { let mut hash_input = Vec::::new(); - self.commitment - .serialize_uncompressed(&mut hash_input) - .unwrap(); + self.commitment.serialize_uncompressed(&mut hash_input)?; hash_input.extend_from_slice(&self.ciphertext); hash_to_g2(&hash_input) @@ -53,12 +53,12 @@ impl Ciphertext { + self.ciphertext.len() } - pub fn to_bytes(&self) -> Vec { - bincode::serialize(self).unwrap() + pub fn to_bytes(&self) -> Result> { + bincode::serialize(self).map_err(|err| err.into()) } - pub fn from_bytes(bytes: &[u8]) -> Self { - bincode::deserialize(bytes).unwrap() + pub fn from_bytes(bytes: &[u8]) -> Result { + bincode::deserialize(bytes).map_err(|err| err.into()) } } @@ -67,7 +67,7 @@ pub fn encrypt( aad: &[u8], pubkey: &E::G1Affine, rng: &mut impl rand::Rng, -) -> Ciphertext { +) -> Result> { // r let rand_element = E::ScalarField::rand(rng); // g @@ -81,20 +81,22 @@ pub fn encrypt( // u let commitment = g_gen.mul(rand_element).into(); - let cipher = shared_secret_to_chacha::(&product); - let nonce = nonce_from_commitment::(commitment); - let ciphertext = cipher.encrypt(&nonce, message).unwrap(); + let nonce = nonce_from_commitment::(commitment)?; + let ciphertext = shared_secret_to_chacha::(&product)? + .encrypt(&nonce, message) + .map_err(ThresholdEncryptionError::SymmetricEncryptionError)? + .to_vec(); // w - let auth_tag = construct_tag_hash::(commitment, &ciphertext, aad) + let auth_tag = construct_tag_hash::(commitment, &ciphertext, aad)? .mul(rand_element) .into(); // TODO: Consider adding aad to the Ciphertext struct - Ciphertext:: { + Ok(Ciphertext:: { commitment, ciphertext, auth_tag, - } + }) } /// Implements the check section 4.4.2 of the Ferveo paper, 'TPKE.CheckCiphertextValidity(U,W,aad)' @@ -110,7 +112,7 @@ pub fn check_ciphertext_validity( c.commitment, &c.ciphertext[..], aad, - )); + )?); let is_ciphertext_valid = E::multi_pairing( // e(U, H_G2(U, aad)) = e(G, W) @@ -145,13 +147,13 @@ fn decrypt_with_shared_secret_unchecked( ciphertext: &Ciphertext, shared_secret: &E::TargetField, ) -> Result> { - let nonce = nonce_from_commitment::(ciphertext.commitment); + let nonce = nonce_from_commitment::(ciphertext.commitment)?; let ciphertext = ciphertext.ciphertext.to_vec(); - let cipher = shared_secret_to_chacha::(shared_secret); - let plaintext = cipher + let plaintext = shared_secret_to_chacha::(shared_secret)? .decrypt(&nonce, ciphertext.as_ref()) - .map_err(|_| ThresholdEncryptionError::CiphertextVerificationFailed)?; + .map_err(|_| ThresholdEncryptionError::CiphertextVerificationFailed)? + .to_vec(); Ok(plaintext) } @@ -175,37 +177,39 @@ fn sha256(input: &[u8]) -> Vec { pub fn shared_secret_to_chacha( s: &E::TargetField, -) -> ChaCha20Poly1305 { +) -> Result { let mut prf_key = Vec::new(); - s.serialize_uncompressed(&mut prf_key).unwrap(); + s.serialize_uncompressed(&mut prf_key)?; let prf_key_32 = sha256(&prf_key); - ChaCha20Poly1305::new(GenericArray::from_slice(&prf_key_32)) + Ok(ChaCha20Poly1305::new(GenericArray::from_slice(&prf_key_32))) } -fn nonce_from_commitment(commitment: E::G1Affine) -> Nonce { +fn nonce_from_commitment(commitment: E::G1Affine) -> Result { let mut commitment_bytes = Vec::new(); - commitment - .serialize_uncompressed(&mut commitment_bytes) - .unwrap(); + commitment.serialize_uncompressed(&mut commitment_bytes)?; let commitment_hash = sha256(&commitment_bytes); - *Nonce::from_slice(&commitment_hash[..12]) + Ok(*Nonce::from_slice(&commitment_hash[..12])) } -fn hash_to_g2(message: &[u8]) -> T { +fn hash_to_g2( + message: &[u8], +) -> Result { let point = htp_bls12381_g2(message); let mut point_ser: Vec = Vec::new(); - point.serialize_uncompressed(&mut point_ser).unwrap(); - T::deserialize_uncompressed(&point_ser[..]).unwrap() + point.serialize_uncompressed(&mut point_ser)?; + T::deserialize_uncompressed(&point_ser[..]).map_err(|err| { + ThresholdEncryptionError::ArkworksSerializationError(err).into() + }) } fn construct_tag_hash( commitment: E::G1Affine, stream_ciphertext: &[u8], aad: &[u8], -) -> E::G2Affine { +) -> Result { let mut hash_input = Vec::::new(); - commitment.serialize_uncompressed(&mut hash_input).unwrap(); + commitment.serialize_uncompressed(&mut hash_input)?; hash_input.extend_from_slice(stream_ciphertext); hash_input.extend_from_slice(aad); hash_to_g2(&hash_input) @@ -229,9 +233,9 @@ mod tests { let aad: &[u8] = "my-aad".as_bytes(); let pubkey = G1Projective::rand(rng).into_affine(); - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); let deserialized: Ciphertext = - Ciphertext::from_bytes(&ciphertext.to_bytes()); + Ciphertext::from_bytes(&ciphertext.to_bytes().unwrap()).unwrap(); assert_eq!(ciphertext, deserialized) } @@ -248,7 +252,7 @@ mod tests { setup_fast::(threshold, shares_num, rng); let g_inv = &contexts[0].setup_params.g_inv; - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); let plaintext = decrypt_symmetric(&ciphertext, aad, &privkey, g_inv).unwrap(); @@ -265,7 +269,7 @@ mod tests { let aad: &[u8] = "my-aad".as_bytes(); let (pubkey, _, contexts) = setup_fast::(threshold, shares_num, rng); let g_inv = contexts[0].setup_params.g_inv.clone(); - let mut ciphertext = encrypt::(msg, aad, &pubkey, rng); + let mut ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); // So far, the ciphertext is valid assert!(check_ciphertext_validity(&ciphertext, aad, &g_inv).is_ok()); diff --git a/tpke/src/decryption.rs b/tpke/src/decryption.rs index bd51cbf6..1dbb17f5 100644 --- a/tpke/src/decryption.rs +++ b/tpke/src/decryption.rs @@ -24,12 +24,12 @@ pub struct DecryptionShareFast { } impl DecryptionShareFast { - pub fn to_bytes(&self) -> Vec { - bincode::serialize(&self).unwrap() + pub fn to_bytes(&self) -> Result> { + bincode::serialize(&self).map_err(|err| err.into()) } - pub fn from_bytes(bytes: &[u8]) -> Self { - bincode::deserialize(bytes).unwrap() + pub fn from_bytes(bytes: &[u8]) -> Result { + bincode::deserialize(bytes).map_err(|err| err.into()) } } @@ -44,13 +44,20 @@ impl ValidatorShareChecksum { pub fn new( validator_decryption_key: &E::ScalarField, ciphertext: &Ciphertext, - ) -> Self { + ) -> Result { // C_i = dk_i^{-1} * U let checksum = ciphertext .commitment - .mul(validator_decryption_key.inverse().unwrap()) + // TODO: Should we panic here? I think we should since that would mean that the decryption key is invalid. + // And so, the validator should not be able to create a decryption share. + // And so, the validator should remake their keypair. + .mul( + validator_decryption_key + .inverse() + .expect("Inverse of this key doesn't exist"), + ) .into_affine(); - Self { checksum } + Ok(Self { checksum }) } pub fn verify( @@ -111,12 +118,12 @@ impl DecryptionShareSimple { g_inv: &E::G1Prepared, ) -> Result { check_ciphertext_validity::(ciphertext, aad, g_inv)?; - Ok(Self::create_unchecked( + Self::create_unchecked( validator_index, validator_decryption_key, private_key_share, ciphertext, - )) + ) } /// Create a decryption share from the given parameters. @@ -126,7 +133,7 @@ impl DecryptionShareSimple { validator_decryption_key: &E::ScalarField, private_key_share: &PrivateKeyShare, ciphertext: &Ciphertext, - ) -> Self { + ) -> Result { // D_i = e(U, Z_i) let decryption_share = E::pairing( ciphertext.commitment, @@ -135,13 +142,13 @@ impl DecryptionShareSimple { .0; let validator_checksum = - ValidatorShareChecksum::new(validator_decryption_key, ciphertext); + ValidatorShareChecksum::new(validator_decryption_key, ciphertext)?; - Self { + Ok(Self { decrypter_index: validator_index, decryption_share, validator_checksum, - } + }) } /// Verify that the decryption share is valid. pub fn verify( @@ -160,12 +167,12 @@ impl DecryptionShareSimple { ) } - pub fn from_bytes(bytes: &[u8]) -> Self { - bincode::deserialize(bytes).unwrap() + pub fn from_bytes(bytes: &[u8]) -> Result { + bincode::deserialize(bytes).map_err(|err| err.into()) } - pub fn to_bytes(&self) -> Vec { - bincode::serialize(&self).unwrap() + pub fn to_bytes(&self) -> Result> { + bincode::serialize(&self).map_err(|err| err.into()) } } @@ -194,13 +201,13 @@ impl DecryptionShareSimplePrecomputed { ) -> Result { check_ciphertext_validity::(ciphertext, aad, g_inv)?; - Ok(Self::create_unchecked( + Self::create_unchecked( validator_index, validator_decryption_key, private_key_share, ciphertext, lagrange_coeff, - )) + ) } pub fn create_unchecked( @@ -209,7 +216,7 @@ impl DecryptionShareSimplePrecomputed { private_key_share: &PrivateKeyShare, ciphertext: &Ciphertext, lagrange_coeff: &E::ScalarField, - ) -> Self { + ) -> Result { // U_{λ_i} = [λ_{i}(0)] U let u_to_lagrange_coeff = ciphertext.commitment.mul(lagrange_coeff); // C_{λ_i} = e(U_{λ_i}, Z_i) @@ -220,13 +227,13 @@ impl DecryptionShareSimplePrecomputed { .0; let validator_checksum = - ValidatorShareChecksum::new(validator_decryption_key, ciphertext); + ValidatorShareChecksum::new(validator_decryption_key, ciphertext)?; - Self { + Ok(Self { decrypter_index: validator_index, decryption_share, validator_checksum, - } + }) } /// Verify that the decryption share is valid. @@ -246,12 +253,12 @@ impl DecryptionShareSimplePrecomputed { ) } - pub fn from_bytes(bytes: &[u8]) -> Self { - bincode::deserialize(bytes).unwrap() + pub fn from_bytes(bytes: &[u8]) -> Result { + bincode::deserialize(bytes).map_err(|e| e.into()) } - pub fn to_bytes(&self) -> Vec { - bincode::serialize(self).unwrap() + pub fn to_bytes(&self) -> Result> { + bincode::serialize(self).map_err(|e| e.into()) } } @@ -400,9 +407,9 @@ mod tests { decryption_share: ark_bls12_381::G1Affine::generator(), }; - let serialized = decryption_share.to_bytes(); + let serialized = decryption_share.to_bytes().unwrap(); let deserialized: DecryptionShareFast = - DecryptionShareFast::from_bytes(&serialized); - assert_eq!(serialized, deserialized.to_bytes()) + DecryptionShareFast::from_bytes(&serialized).unwrap(); + assert_eq!(serialized, deserialized.to_bytes().unwrap()) } } diff --git a/tpke/src/lib.rs b/tpke/src/lib.rs index 7c1fa889..d0231a42 100644 --- a/tpke/src/lib.rs +++ b/tpke/src/lib.rs @@ -49,6 +49,18 @@ pub enum ThresholdEncryptionError { /// Plaintext verification failed #[error("Plaintext verification failed")] PlaintextVerificationFailed, + + /// Serialization failed + #[error("Bytes serialization failed")] + BytesSerializationError(#[from] bincode::Error), + + /// Symmetric encryption failed" + #[error("Symmetric encryption failed")] + SymmetricEncryptionError(chacha20poly1305::aead::Error), + + /// Serialization failed + #[error("Arkworks serialization failed")] + ArkworksSerializationError(#[from] ark_serialize::SerializationError), } pub type Result = anyhow::Result; @@ -309,12 +321,13 @@ mod tests { let (pubkey, _, _) = setup_fast::(threshold, shares_num, rng); - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); - let serialized = ciphertext.to_bytes(); - let deserialized: Ciphertext = Ciphertext::from_bytes(&serialized); + let serialized = ciphertext.to_bytes().unwrap(); + let deserialized: Ciphertext = + Ciphertext::from_bytes(&serialized).unwrap(); - assert_eq!(serialized, deserialized.to_bytes()) + assert_eq!(serialized, deserialized.to_bytes().unwrap()) } fn test_ciphertext_validation_fails( @@ -418,7 +431,7 @@ mod tests { let aad: &[u8] = "my-aad".as_bytes(); let (pubkey, _, contexts) = setup_fast::(threshold, shares_num, rng); - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); let bad_aad = "bad aad".as_bytes(); assert!(contexts[0].create_share(&ciphertext, bad_aad).is_err()); @@ -434,7 +447,7 @@ mod tests { let (pubkey, _, contexts) = setup_simple::(threshold, shares_num, rng); - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); let bad_aad = "bad aad".as_bytes(); assert!(contexts[0].create_share(&ciphertext, bad_aad).is_err()); @@ -450,7 +463,7 @@ mod tests { let (pubkey, _, contexts) = setup_fast::(threshold, shares_num, &mut rng); - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); let g_inv = &contexts[0].setup_params.g_inv; let mut decryption_shares: Vec> = vec![]; @@ -500,7 +513,7 @@ mod tests { setup_simple::(threshold, shares_num, &mut rng); let g_inv = &contexts[0].setup_params.g_inv; - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); let decryption_shares: Vec<_> = contexts .iter() @@ -532,7 +545,7 @@ mod tests { let (pubkey, _, contexts) = setup_simple::(threshold, shares_num, &mut rng); let g_inv = &contexts[0].setup_params.g_inv; - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); let decryption_shares: Vec<_> = contexts .iter() @@ -578,7 +591,7 @@ mod tests { let (pubkey, _, contexts) = setup_simple::(threshold, shares_num, &mut rng); - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); let decryption_shares: Vec<_> = contexts .iter() @@ -693,7 +706,7 @@ mod tests { let (pubkey, _, contexts) = setup_simple::(threshold, shares_num, rng); let g_inv = &contexts[0].setup_params.g_inv; - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); // Create an initial shared secret let old_shared_secret = @@ -775,7 +788,7 @@ mod tests { setup_simple::(threshold, shares_num, rng); let g_inv = &contexts[0].setup_params.g_inv; let pub_contexts = contexts[0].public_decryption_contexts.clone(); - let ciphertext = encrypt::(msg, aad, &pubkey, rng); + let ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); // Create an initial shared secret let old_shared_secret = From 0b9504833ff4025236d9821c5bdc40e66f6774d6 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Thu, 16 Feb 2023 16:19:55 +0100 Subject: [PATCH 27/36] trim external apis --- ferveo-common/src/lib.rs | 9 +++ ferveo-python/src/lib.rs | 33 +++++---- ferveo/src/api.rs | 147 ++++++++++---------------------------- ferveo/src/lib.rs | 69 ++++++++++-------- ferveo/src/vss/pvss.rs | 63 ++++++---------- tpke-wasm/src/lib.rs | 71 +++++++++--------- tpke-wasm/tests/node.rs | 19 +++-- tpke/src/api.rs | 113 ++++++----------------------- tpke/src/hash_to_curve.rs | 4 +- 9 files changed, 199 insertions(+), 329 deletions(-) diff --git a/ferveo-common/src/lib.rs b/ferveo-common/src/lib.rs index f05e3ea3..61e7ef41 100644 --- a/ferveo-common/src/lib.rs +++ b/ferveo-common/src/lib.rs @@ -15,6 +15,15 @@ pub struct ExternalValidator { pub public_key: PublicKey, } +impl ExternalValidator { + pub fn new(address: String, public_key: PublicKey) -> Self { + Self { + address, + public_key, + } + } +} + #[derive(Clone, Debug)] pub struct Validator { pub validator: ExternalValidator, diff --git a/ferveo-python/src/lib.rs b/ferveo-python/src/lib.rs index 01b61180..4bced028 100644 --- a/ferveo-python/src/lib.rs +++ b/ferveo-python/src/lib.rs @@ -12,7 +12,8 @@ pub fn encrypt( aad: &[u8], public_key: &DkgPublicKey, ) -> PyResult { - let ciphertext = ferveo::api::encrypt(message, aad, &public_key.0) + let rng = &mut thread_rng(); + let ciphertext = ferveo::api::encrypt(message, aad, &public_key.0, rng) .map_err(|err| PyValueError::new_err(format!("{}", err)))?; Ok(Ciphertext(ciphertext)) } @@ -23,7 +24,7 @@ pub fn combine_decryption_shares(shares: Vec) -> SharedSecret { .iter() .map(|share| share.0.clone()) .collect::>(); - SharedSecret(ferveo::api::combine_decryption_shares(&shares)) + SharedSecret(ferveo::api::share_combine_simple_precomputed(&shares)) } #[pyfunction] @@ -43,11 +44,11 @@ pub fn decrypt_with_shared_secret( } #[pyclass(module = "ferveo")] -#[derive(derive_more::From, derive_more::AsRef)] +#[derive(derive_more::AsRef)] pub struct G1Prepared(ferveo::api::G1Prepared); #[pyclass(module = "ferveo")] -#[derive(derive_more::From, derive_more::AsRef)] +#[derive(derive_more::AsRef)] pub struct SharedSecret(ferveo::api::SharedSecret); #[pyclass(module = "ferveo")] @@ -61,6 +62,8 @@ impl Keypair { Self(ferveo::api::Keypair::new(&mut thread_rng())) } + // TODO: Consider moving from_bytes and __bytes__ to a separate trait + #[staticmethod] pub fn from_bytes(bytes: &[u8]) -> PyResult { let keypair = ferveo::api::Keypair::from_bytes(bytes) @@ -106,7 +109,7 @@ impl PublicKey { #[pyclass(module = "ferveo")] #[derive(Clone, derive_more::From, derive_more::AsRef)] -pub struct ExternalValidator(ferveo::api::ExternalValidator); +pub struct ExternalValidator(ferveo::api::ExternalValidator); #[pymethods] impl ExternalValidator { @@ -118,7 +121,7 @@ impl ExternalValidator { #[pyclass(module = "ferveo")] #[derive(Clone, derive_more::From, derive_more::AsRef)] -pub struct Transcript(ferveo::api::Transcript); +pub struct Transcript(ferveo::api::Transcript); #[pymethods] impl Transcript { @@ -214,13 +217,17 @@ impl AggregatedTranscript { ciphertext: &Ciphertext, aad: &[u8], validator_keypair: &Keypair, - ) -> DecryptionShare { - DecryptionShare(self.0.create_decryption_share( - &dkg.0, - &ciphertext.0, - aad, - &validator_keypair.0, - )) + ) -> PyResult { + let decryption_share = self + .0 + .create_decryption_share( + &dkg.0, + &ciphertext.0, + aad, + &validator_keypair.0, + ) + .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + Ok(DecryptionShare(decryption_share)) } #[staticmethod] diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index 11cb8c40..8090ea24 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -1,79 +1,18 @@ use ark_poly::EvaluationDomain; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; -use bincode::Options; use ferveo_common::serialization::ser::serialize; -pub use ferveo_common::{Keypair, PublicKey}; +pub use ferveo_common::{ExternalValidator, Keypair, PublicKey}; use group_threshold_cryptography as tpke; -use group_threshold_cryptography::api::TpkeResult; use rand::rngs::StdRng; use rand::{thread_rng, RngCore, SeedableRng}; use serde::{Deserialize, Serialize}; +pub use tpke::api::{ + decrypt_with_shared_secret, encrypt, share_combine_simple_precomputed, + Ciphertext, DecryptionShareSimplePrecomputed as DecryptionShare, + DkgPublicKey, G1Prepared, Result, SharedSecret, UnblindingKey, E, +}; -pub type E = ark_bls12_381::Bls12_381; - -pub fn encrypt( - message: &[u8], - aad: &[u8], - public_key: &DkgPublicKey, -) -> TpkeResult { - Ok(Ciphertext(tpke::api::encrypt(message, aad, &public_key.0)?)) -} - -pub fn combine_decryption_shares( - decryption_shares: &[DecryptionShare], -) -> SharedSecret { - let shares = decryption_shares - .iter() - .map(|share| share.0.clone()) - .collect::>(); - SharedSecret(tpke::share_combine_simple_precomputed::(&shares)) -} - -pub fn decrypt_with_shared_secret( - ciphertext: &Ciphertext, - aad: &[u8], - shared_secret: &SharedSecret, - g_inv: &G1Prepared, -) -> TpkeResult> { - tpke::api::decrypt_with_shared_secret( - &ciphertext.0, - aad, - &shared_secret.0, - &g_inv.0, - ) -} - -pub struct G1Prepared(pub tpke::api::TpkeG1Prepared); - -pub struct SharedSecret(tpke::api::TpkeSharedSecret); - -#[derive(Clone)] -pub struct ExternalValidator(ferveo_common::ExternalValidator); - -impl ExternalValidator { - pub fn new(address: String, public_key: PublicKey) -> Self { - Self(ferveo_common::ExternalValidator { - address, - public_key, - }) - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Transcript(crate::PubliclyVerifiableSS); - -impl Transcript { - pub fn from_bytes(bytes: &[u8]) -> Result { - Ok(Self(bincode::deserialize(bytes)?)) - } - - pub fn to_bytes(&self) -> Result, crate::Error> { - Ok(bincode::serialize(&self.0)?) - } -} - -#[derive(Clone)] -pub struct DkgPublicKey(pub tpke::api::TpkeDkgPublicKey); +pub use crate::PubliclyVerifiableSS as Transcript; #[derive(Clone)] pub struct Dkg(crate::PubliclyVerifiableDkg); @@ -83,14 +22,9 @@ impl Dkg { tau: u64, shares_num: u32, security_threshold: u32, - validators: &[ExternalValidator], - me: &ExternalValidator, - ) -> Result { - let validators = &validators - .iter() - .map(|v| v.0.clone()) - .collect::>>(); - let me = &me.0; + validators: &[ExternalValidator], + me: &ExternalValidator, + ) -> Result { let params = crate::Params { tau, security_threshold, @@ -109,36 +43,29 @@ impl Dkg { } pub fn final_key(&self) -> DkgPublicKey { - DkgPublicKey(self.0.final_key()) + self.0.final_key() } pub fn generate_transcript( &self, rng: &mut R, - ) -> Result { - Ok(Transcript(self.0.create_share(rng)?)) + ) -> Result> { + self.0.create_share(rng) } pub fn aggregate_transcripts( &mut self, - messages: &Vec<(ExternalValidator, Transcript)>, - ) -> Result { + messages: &Vec<(ExternalValidator, Transcript)>, + ) -> Result { // Avoid mutating current state // TODO: Rewrite `deal` to not require mutability after validating this API design for (validator, transcript) in messages { - self.0.deal(validator.0.clone(), transcript.0.clone())?; + self.0.deal(validator.clone(), transcript.clone())?; } Ok(AggregatedTranscript(crate::pvss::aggregate(&self.0))) } } -pub struct Ciphertext(pub tpke::api::Ciphertext); - -pub struct UnblindingKey(tpke::api::TpkeUnblindingKey); - -#[derive(Clone)] -pub struct DecryptionShare(tpke::api::TpkeDecryptionShareSimplePrecomputed); - #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AggregatedTranscript( crate::PubliclyVerifiableSS, @@ -155,23 +82,23 @@ impl AggregatedTranscript { ciphertext: &Ciphertext, aad: &[u8], validator_keypair: &Keypair, - ) -> DecryptionShare { + ) -> Result { let domain_points: Vec<_> = dkg.0.domain.elements().collect(); - DecryptionShare(self.0.make_decryption_share_simple_precomputed( - &ciphertext.0 .0, + self.0.make_decryption_share_simple_precomputed( + ciphertext, aad, &validator_keypair.decryption_key, dkg.0.me, &domain_points, &dkg.0.pvss_params.g_inv(), - )) + ) } - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_bytes(bytes: &[u8]) -> Result { Ok(Self(bincode::deserialize(bytes)?)) } - pub fn to_bytes(&self) -> Result, crate::Error> { + pub fn to_bytes(&self) -> Result> { Ok(bincode::serialize(&self.0)?) } } @@ -207,11 +134,9 @@ mod test_ferveo_api { let validators = validator_keypairs .iter() .enumerate() - .map(|(i, keypair)| { - ExternalValidator(ferveo_common::ExternalValidator { - address: format!("validator-{}", i), - public_key: keypair.public(), - }) + .map(|(i, keypair)| ExternalValidator { + address: format!("validator-{}", i), + public_key: keypair.public(), }) .collect::>(); @@ -246,7 +171,8 @@ mod test_ferveo_api { // In the meantime, the client creates a ciphertext and decryption request let msg: &[u8] = "abc".as_bytes(); let aad: &[u8] = "my-aad".as_bytes(); - let ciphertext = encrypt(msg, aad, &public_key).unwrap(); + let rng = &mut thread_rng(); + let ciphertext = encrypt(msg, aad, &public_key, rng).unwrap(); // Having aggregated the transcripts, the validators can now create decryption shares let decryption_shares: Vec<_> = izip!(&validators, &validator_keypairs) @@ -262,25 +188,28 @@ mod test_ferveo_api { .unwrap(); let aggregate = dkg.aggregate_transcripts(&messages).unwrap(); assert!(pvss_aggregated.validate(&dkg)); - aggregate.create_decryption_share( - &dkg, - &ciphertext, - aad, - validator_keypair, - ) + aggregate + .create_decryption_share( + &dkg, + &ciphertext, + aad, + validator_keypair, + ) + .unwrap() }) .collect(); // Now, the decryption share can be used to decrypt the ciphertext // This part is part of the client API - let shared_secret = combine_decryption_shares(&decryption_shares); + let shared_secret = + share_combine_simple_precomputed(&decryption_shares); let plaintext = decrypt_with_shared_secret( &ciphertext, aad, &shared_secret, - &G1Prepared(dkg.0.pvss_params.g_inv()), + &dkg.0.pvss_params.g_inv(), ) .unwrap(); assert_eq!(plaintext, msg); diff --git a/ferveo/src/lib.rs b/ferveo/src/lib.rs index acecf949..f903392b 100644 --- a/ferveo/src/lib.rs +++ b/ferveo/src/lib.rs @@ -5,6 +5,7 @@ pub mod dkg; pub mod primitives; mod vss; +// TODO: Replace with concrete error type pub use anyhow::Error; pub use dkg::*; pub use primitives::*; @@ -69,13 +70,15 @@ mod test_dkg_full { .iter() .enumerate() .map(|(validator_index, validator_keypair)| { - pvss_aggregated.make_decryption_share_simple( - ciphertext, - aad, - &validator_keypair.decryption_key, - validator_index, - &dkg.pvss_params.g_inv(), - ) + pvss_aggregated + .make_decryption_share_simple( + ciphertext, + aad, + &validator_keypair.decryption_key, + validator_index, + &dkg.pvss_params.g_inv(), + ) + .unwrap() }) .collect(); @@ -151,14 +154,16 @@ mod test_dkg_full { .iter() .enumerate() .map(|(validator_index, validator_keypair)| { - pvss_aggregated.make_decryption_share_simple_precomputed( - &ciphertext, - aad, - &validator_keypair.decryption_key, - validator_index, - &domain_points, - &dkg.pvss_params.g_inv(), - ) + pvss_aggregated + .make_decryption_share_simple_precomputed( + &ciphertext, + aad, + &validator_keypair.decryption_key, + validator_index, + &domain_points, + &dkg.pvss_params.g_inv(), + ) + .unwrap() }) .collect(); @@ -320,13 +325,15 @@ mod test_dkg_full { .iter() .enumerate() .map(|(validator_index, validator_keypair)| { - pvss_aggregated.make_decryption_share_simple( - &ciphertext, - aad, - &validator_keypair.decryption_key, - validator_index, - &dkg.pvss_params.g_inv(), - ) + pvss_aggregated + .make_decryption_share_simple( + &ciphertext, + aad, + &validator_keypair.decryption_key, + validator_index, + &dkg.pvss_params.g_inv(), + ) + .unwrap() }) .collect(); @@ -391,14 +398,16 @@ mod test_dkg_full { .iter() .enumerate() .map(|(validator_index, validator_keypair)| { - pvss_aggregated.refresh_decryption_share( - &ciphertext, - aad, - &validator_keypair.decryption_key, - validator_index, - &polynomial, - &dkg, - ) + pvss_aggregated + .refresh_decryption_share( + &ciphertext, + aad, + &validator_keypair.decryption_key, + validator_index, + &polynomial, + &dkg, + ) + .unwrap() }) .collect(); diff --git a/ferveo/src/vss/pvss.rs b/ferveo/src/vss/pvss.rs index 43382005..0489f580 100644 --- a/ferveo/src/vss/pvss.rs +++ b/ferveo/src/vss/pvss.rs @@ -189,6 +189,14 @@ impl PubliclyVerifiableSS { E::pairing(dkg.pvss_params.g, *y_i) == E::pairing(a_i, ek_i) }) } + + pub fn from_bytes(bytes: &[u8]) -> Result { + bincode::deserialize(bytes).map_err(|err| err.into()) + } + + pub fn to_bytes(&self) -> Result> { + bincode::serialize(&self).map_err(|err| err.into()) + } } /// Extra methods available to aggregated PVSS transcripts @@ -231,7 +239,11 @@ impl PubliclyVerifiableSS { .shares .get(validator_index) .unwrap() - .mul(validator_decryption_key.inverse().unwrap()) + .mul( + validator_decryption_key + .inverse() + .expect("Validator decryption key must have an inverse"), + ) .into_affine(); PrivateKeyShare { private_key_share } } @@ -243,7 +255,7 @@ impl PubliclyVerifiableSS { validator_decryption_key: &E::ScalarField, validator_index: usize, g_inv: &E::G1Prepared, - ) -> DecryptionShareSimple { + ) -> Result> { let private_key_share = self.decrypt_private_key_share( validator_decryption_key, validator_index, @@ -256,7 +268,6 @@ impl PubliclyVerifiableSS { aad, g_inv, ) - .unwrap() // TODO: Add proper error handling } pub fn make_decryption_share_simple_precomputed( @@ -267,7 +278,7 @@ impl PubliclyVerifiableSS { validator_index: usize, domain_points: &[E::ScalarField], g_inv: &E::G1Prepared, - ) -> DecryptionShareSimplePrecomputed { + ) -> Result> { let private_key_share = self.decrypt_private_key_share( validator_decryption_key, validator_index, @@ -284,7 +295,6 @@ impl PubliclyVerifiableSS { &lagrange_coeffs[validator_index], g_inv, ) - .unwrap() // TODO: Add proper error handling } pub fn refresh_decryption_share( @@ -295,13 +305,12 @@ impl PubliclyVerifiableSS { validator_index: usize, polynomial: &DensePolynomial, dkg: &PubliclyVerifiableDkg, - ) -> DecryptionShareSimple { + ) -> Result> { let validator_private_key_share = self.decrypt_private_key_share( validator_decryption_key, validator_index, ); let h = dkg.pvss_params.h; - let _g_inv = dkg.pvss_params.g_inv(); let domain_point = dkg.domain.element(validator_index); let refreshed_private_key_share = refresh_private_key_share( &h, @@ -317,7 +326,6 @@ impl PubliclyVerifiableSS { aad, &dkg.pvss_params.g_inv(), ) - .unwrap() // TODO: Add proper error handling } pub fn update_private_key_share_for_recovery( @@ -387,7 +395,10 @@ pub fn aggregate_for_decryption( .values() .map(|pvss| pvss.shares.clone()) .collect::>(); - let first_share = shares.first().unwrap().to_vec(); + let first_share = shares + .first() + .expect("Need one or more decryption shares to aggregate") + .to_vec(); shares .into_iter() .skip(1) @@ -400,40 +411,6 @@ pub fn aggregate_for_decryption( }) } -pub fn make_decryption_shares( - ciphertext: &Ciphertext, - validator_keypairs: &[Keypair], - aggregate: &[E::G2Affine], - aad: &[u8], - g_inv: &E::G1Prepared, -) -> Vec> { - // TODO: Calculate separately for each validator - aggregate - .iter() - .zip_eq(validator_keypairs.iter()) - .enumerate() - .map(|(decrypter_index, (encrypted_share, keypair))| { - // Decrypt private key shares https://nikkolasg.github.io/ferveo/pvss.html#validator-decryption-of-private-key-shares - let z_i = - encrypted_share.mul(keypair.decryption_key.inverse().unwrap()); - // TODO: Consider using "container" structs from `tpke` for other primitives - let private_key_share = PrivateKeyShare { - private_key_share: z_i.into_affine(), - }; - - DecryptionShareSimple::create( - decrypter_index, - &keypair.decryption_key, - &private_key_share, - ciphertext, - aad, - g_inv, - ) - .unwrap() // Unwrapping here only because this is a test method! - }) - .collect::>() -} - #[cfg(test)] mod test_pvss { use ark_bls12_381::Bls12_381 as EllipticCurve; diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index 07259cd4..91bfd09f 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -13,7 +13,7 @@ extern crate wee_alloc; #[wasm_bindgen] #[derive(Clone, Debug, PartialEq)] -pub struct G1Prepared(tpke::api::TpkeG1Prepared); +pub struct G1Prepared(tpke::api::G1Prepared); #[wasm_bindgen] #[derive(Clone, Debug, PartialEq)] @@ -64,7 +64,7 @@ impl DecryptionShareSimplePrecomputed { #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct PublicKey( #[serde_as(as = "ferveo_common::serialization::SerdeAs")] - pub(crate) tpke::api::TpkeDkgPublicKey, + pub(crate) tpke::api::DkgPublicKey, ); #[wasm_bindgen] @@ -72,9 +72,8 @@ impl PublicKey { #[wasm_bindgen] pub fn from_bytes(bytes: &[u8]) -> Result { let mut reader = bytes; - let pk = - tpke::api::TpkeDkgPublicKey::deserialize_uncompressed(&mut reader) - .map_err(map_js_err)?; + let pk = tpke::api::DkgPublicKey::deserialize_uncompressed(&mut reader) + .map_err(map_js_err)?; Ok(PublicKey(pk)) } @@ -93,7 +92,7 @@ impl PublicKey { #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct PrivateKey( #[serde_as(as = "ferveo_common::serialization::SerdeAs")] - pub(crate) tpke::api::TpkePrivateKey, + pub(crate) tpke::api::PrivateKey, ); #[wasm_bindgen] @@ -101,9 +100,8 @@ impl PrivateKey { #[wasm_bindgen] pub fn from_bytes(bytes: &[u8]) -> Result { let mut reader = bytes; - let pk = - tpke::api::TpkePrivateKey::deserialize_uncompressed(&mut reader) - .map_err(map_js_err)?; + let pk = tpke::api::PrivateKey::deserialize_uncompressed(&mut reader) + .map_err(map_js_err)?; Ok(PrivateKey(pk)) } @@ -141,8 +139,9 @@ pub fn encrypt( public_key: &PublicKey, ) -> Result { set_panic_hook(); - let ciphertext = - tpke::api::encrypt(message, aad, &public_key.0).map_err(map_js_err)?; + let rng = &mut rand::thread_rng(); + let ciphertext = tpke::api::encrypt(message, aad, &public_key.0, rng) + .map_err(map_js_err)?; Ok(Ciphertext(ciphertext)) } @@ -152,9 +151,10 @@ pub fn decrypt_with_private_key( aad: &[u8], private_key: &PrivateKey, g_inv: &G1Prepared, -) -> Vec { +) -> Result, Error> { set_panic_hook(); tpke::api::decrypt_symmetric(&ciphertext.0, aad, &private_key.0, &g_inv.0) + .map_err(map_js_err) } #[wasm_bindgen] @@ -163,12 +163,12 @@ pub struct DomainPoint(tpke::api::DomainPoint); #[wasm_bindgen] #[derive(Clone, Debug)] -pub struct SharedSecret(tpke::api::TpkeSharedSecret); +pub struct SharedSecret(tpke::api::SharedSecret); #[wasm_bindgen] #[derive(Clone, Debug)] pub struct SharedSecretPrecomputedBuilder { - shares: Vec, + shares: Vec, threshold: usize, } @@ -187,7 +187,7 @@ impl SharedSecretPrecomputedBuilder { &mut self, share: &DecryptionShareSimplePrecomputed, ) { - self.shares.push(share.0 .0.clone()); + self.shares.push(share.0.clone()); } #[wasm_bindgen] @@ -203,8 +203,8 @@ impl SharedSecretPrecomputedBuilder { #[wasm_bindgen] #[derive(Clone, Debug)] pub struct SharedSecretSimpleBuilder { - shares: Vec, - domain_points: Vec, + shares: Vec, + domain_points: Vec, threshold: usize, } @@ -221,12 +221,12 @@ impl SharedSecretSimpleBuilder { #[wasm_bindgen] pub fn add_decryption_share(&mut self, share: &DecryptionShareSimple) { - self.shares.push(share.0 .0.clone()); + self.shares.push(share.0.clone()); } #[wasm_bindgen] pub fn add_domain_point(&mut self, domain_point: &DomainPoint) { - self.domain_points.push(domain_point.0 .0); + self.domain_points.push(domain_point.0.clone()); } #[wasm_bindgen] @@ -235,8 +235,10 @@ impl SharedSecretSimpleBuilder { if self.shares.len() < self.threshold { panic!("Number of shares below threshold"); } + let domain_points: Vec<_> = + self.domain_points.iter().map(|x| x.0).collect(); let lagrange_coeffs = - tpke::prepare_combine_simple::(&self.domain_points); + tpke::prepare_combine_simple::(&domain_points); SharedSecret(tpke::share_combine_simple(&self.shares, &lagrange_coeffs)) } } @@ -247,7 +249,7 @@ pub fn decrypt_with_shared_secret( aad: &[u8], shared_secret: &SharedSecret, g_inv: &G1Prepared, -) -> Vec { +) -> Result, Error> { set_panic_hook(); tpke::api::decrypt_with_shared_secret( &ciphertext.0, @@ -255,7 +257,7 @@ pub fn decrypt_with_shared_secret( &shared_secret.0, &g_inv.0, ) - .unwrap() + .map_err(map_js_err) } /// Factory functions for testing @@ -267,7 +269,7 @@ pub mod test_common { pub struct Dkg { pub public_key: PublicKey, pub private_key: PrivateKey, - private_contexts: Vec, + private_contexts: Vec, } #[wasm_bindgen] @@ -294,12 +296,12 @@ pub mod test_common { ciphertext: &Ciphertext, aad: &[u8], validator_index: usize, - ) -> DecryptionShareSimple { + ) -> Result { set_panic_hook(); - DecryptionShareSimple(tpke::api::DecryptionShareSimple( + Ok(DecryptionShareSimple( self.private_contexts[validator_index] - .create_share(&ciphertext.0 .0, aad) - .unwrap(), + .create_share(&ciphertext.0, aad) + .map_err(map_js_err)?, )) } @@ -309,16 +311,15 @@ pub mod test_common { ciphertext: &Ciphertext, aad: &[u8], validator_index: usize, - ) -> DecryptionShareSimplePrecomputed { + ) -> Result { set_panic_hook(); - DecryptionShareSimplePrecomputed( - tpke::api::DecryptionShareSimplePrecomputed( - self.private_contexts[validator_index] - .create_share_precomputed(&ciphertext.0 .0, aad) - .unwrap(), - ), - ) + Ok(DecryptionShareSimplePrecomputed( + self.private_contexts[validator_index] + .create_share_precomputed(&ciphertext.0, aad) + .map_err(map_js_err)?, + )) } + #[wasm_bindgen] pub fn domain_point(&self, validator_index: usize) -> DomainPoint { set_panic_hook(); diff --git a/tpke-wasm/tests/node.rs b/tpke-wasm/tests/node.rs index 99a57fdc..1ec52aee 100644 --- a/tpke-wasm/tests/node.rs +++ b/tpke-wasm/tests/node.rs @@ -37,7 +37,10 @@ fn tdec_simple() { // Create decryption shares let decryption_shares = (0..threshold) - .map(|i| dkg.make_decryption_share_simple(&ciphertext, &aad, i)) + .map(|i| { + dkg.make_decryption_share_simple(&ciphertext, &aad, i) + .unwrap() + }) .collect::>(); let domain_points = (0..threshold) @@ -77,7 +80,8 @@ fn tdec_simple() { &aad, &shared_secret, &dkg.g_inv(), - ); + ) + .unwrap(); assert_eq!(msg, plaintext) } @@ -116,7 +120,10 @@ fn tdec_simple_precomputed() { // decryption error. let decryption_shares = (0..shares_num) - .map(|i| dkg.make_decryption_share_precomputed(&ciphertext, &aad, i)) + .map(|i| { + dkg.make_decryption_share_precomputed(&ciphertext, &aad, i) + .unwrap() + }) .collect::>(); // Serialize and send back to client @@ -149,7 +156,8 @@ fn tdec_simple_precomputed() { &aad, &shared_secret, &dkg.g_inv(), - ); + ) + .unwrap(); assert_eq!(msg, plaintext) } @@ -170,7 +178,8 @@ fn encrypts_and_decrypts() { &aad, &dkg.private_key, &dkg.g_inv(), - ); + ) + .unwrap(); // TODO: Plaintext is padded to 32 bytes. Fix this. assert_eq!(message, plaintext[..message.len()]) diff --git a/tpke/src/api.rs b/tpke/src/api.rs index 2c20b85c..8d5a4b83 100644 --- a/tpke/src/api.rs +++ b/tpke/src/api.rs @@ -1,113 +1,40 @@ //! Contains the public API of the library. -#![allow(dead_code)] - -// TODO: Refactor this module to deduplicate shared code from tpke-wasm and tpke-wasm. - use ferveo_common::serialization; use serde::{Deserialize, Serialize}; use serde_with::serde_as; pub type E = ark_bls12_381::Bls12_381; -pub type TpkeDkgPublicKey = ark_bls12_381::G1Affine; -pub type TpkeG1Prepared = ::G1Prepared; -pub type TpkeG1Affine = ::G1Affine; -pub type TpkePrivateKey = ark_bls12_381::G2Affine; -pub type TpkeUnblindingKey = ark_bls12_381::Fr; -pub type TpkeDomainPoint = ark_bls12_381::Fr; -pub type TpkeCiphertext = crate::Ciphertext; -pub type TpkeDecryptionShareSimplePrecomputed = - crate::DecryptionShareSimplePrecomputed; -pub type TpkeDecryptionShareSimple = crate::DecryptionShareSimple; -pub type TpkePublicDecryptionContext = crate::PublicDecryptionContextSimple; -pub type TpkeSharedSecret = ::TargetField; -pub type TpkeResult = crate::Result; -pub type TpkePrivateDecryptionContext = +pub type DkgPublicKey = ark_bls12_381::G1Affine; +pub type G1Prepared = ::G1Prepared; +pub type PrivateKey = ark_bls12_381::G2Affine; +pub type UnblindingKey = ark_bls12_381::Fr; +pub type SharedSecret = ::TargetField; +pub type Result = crate::Result; +pub type PrivateDecryptionContextSimple = crate::PrivateDecryptionContextSimple; +pub type DecryptionShareSimplePrecomputed = + crate::DecryptionShareSimplePrecomputed; +pub type DecryptionShareSimple = crate::DecryptionShareSimple; +pub type Ciphertext = crate::Ciphertext; -pub fn encrypt( - message: &[u8], - aad: &[u8], - public_key: &TpkeDkgPublicKey, -) -> TpkeResult { - // TODO: Should rng be a parameter? - let rng = &mut rand::thread_rng(); - Ok(Ciphertext(crate::encrypt(message, aad, public_key, rng)?)) -} - -pub fn decrypt_with_shared_secret( - ciphertext: &Ciphertext, - aad: &[u8], - shared_secret: &TpkeSharedSecret, - g_inv: &TpkeG1Prepared, -) -> TpkeResult> { - crate::decrypt_with_shared_secret(&ciphertext.0, aad, shared_secret, g_inv) -} - -pub fn decrypt_symmetric( - ciphertext: &Ciphertext, - aad: &[u8], - private_key: &TpkePrivateKey, - g_inv: &TpkeG1Prepared, -) -> Vec { - crate::decrypt_symmetric(&ciphertext.0, aad, private_key, g_inv).unwrap() -} +pub use crate::{ + decrypt_symmetric, decrypt_with_shared_secret, encrypt, + share_combine_simple_precomputed, +}; #[serde_as] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DomainPoint( - #[serde_as(as = "serialization::SerdeAs")] pub TpkeDomainPoint, + #[serde_as(as = "serialization::SerdeAs")] pub ark_bls12_381::Fr, ); impl DomainPoint { - pub fn to_bytes(&self) -> Vec { - bincode::serialize(&self).unwrap() - } - - pub fn from_bytes(bytes: &[u8]) -> Self { - bincode::deserialize(bytes).unwrap() - } -} - -#[derive(Clone, Debug, PartialEq)] -pub struct DecryptionShareSimple(pub TpkeDecryptionShareSimple); - -impl DecryptionShareSimple { - pub fn to_bytes(&self) -> TpkeResult> { - self.0.to_bytes() - } - - pub fn from_bytes(bytes: &[u8]) -> TpkeResult { - Ok(Self(TpkeDecryptionShareSimple::from_bytes(bytes)?)) - } -} - -#[derive(Clone, Debug, PartialEq)] -pub struct DecryptionShareSimplePrecomputed( - pub TpkeDecryptionShareSimplePrecomputed, -); - -impl DecryptionShareSimplePrecomputed { - pub fn to_bytes(&self) -> TpkeResult> { - self.0.to_bytes() - } - - pub fn from_bytes(bytes: &[u8]) -> TpkeResult { - Ok(Self(TpkeDecryptionShareSimplePrecomputed::from_bytes( - bytes, - )?)) - } -} - -#[derive(Clone, Debug, PartialEq)] -pub struct Ciphertext(pub TpkeCiphertext); - -impl Ciphertext { - pub fn from_bytes(bytes: &[u8]) -> crate::Result { - Ok(Ciphertext(TpkeCiphertext::from_bytes(bytes)?)) + pub fn to_bytes(&self) -> Result> { + bincode::serialize(&self).map_err(|e| e.into()) } - pub fn to_bytes(&self) -> crate::Result> { - self.0.to_bytes() + pub fn from_bytes(bytes: &[u8]) -> Result { + bincode::deserialize(bytes).map_err(|e| e.into()) } } diff --git a/tpke/src/hash_to_curve.rs b/tpke/src/hash_to_curve.rs index 78592a49..55b75f21 100644 --- a/tpke/src/hash_to_curve.rs +++ b/tpke/src/hash_to_curve.rs @@ -85,7 +85,9 @@ fn to_affine(compressed_rev: &mut [u8; 96]) -> Affine { // .unwrap() // In this workaround we use `from_random_bytes` instead of `deserialize_compressed`, because // the former performs checks that prevent the "Unexpected Flag" error. - ark_bls12_381::G2Affine::from_random_bytes(&compressed_rev[..]).unwrap() + // TODO: Remove expect? + ark_bls12_381::G2Affine::from_random_bytes(&compressed_rev[..]) + .expect("Failed to convert to affine point") } #[cfg(test)] From b9535fefae0795f4b43f726378c5c65d0e776937 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Fri, 17 Feb 2023 17:26:18 +0100 Subject: [PATCH 28/36] refactor serialization --- Cargo.lock | 2 + ferveo-common/src/keypair.rs | 26 ------------ ferveo-common/src/serialization.rs | 44 +++++++++++++++++++++ ferveo-python/Cargo.toml | 1 + ferveo-python/src/lib.rs | 63 +++++++++++++----------------- ferveo/src/api.rs | 8 ---- ferveo/src/vss/pvss.rs | 8 ---- tpke-python/Cargo.toml | 1 + tpke-python/src/lib.rs | 1 + tpke-wasm/src/lib.rs | 29 +++++++------- tpke/src/api.rs | 10 ----- tpke/src/ciphertext.rs | 27 +------------ tpke/src/decryption.rs | 35 +---------------- tpke/src/lib.rs | 1 + 14 files changed, 95 insertions(+), 161 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c560ee11..e0644cf3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -852,6 +852,7 @@ version = "0.1.0" dependencies = [ "derive_more", "ferveo", + "ferveo-common", "group-threshold-cryptography", "pyo3", "pyo3-build-config 0.18.1", @@ -2041,6 +2042,7 @@ dependencies = [ name = "tpke-python" version = "0.1.0" dependencies = [ + "ferveo-common", "group-threshold-cryptography", "pyo3", "pyo3-build-config 0.18.1", diff --git a/ferveo-common/src/keypair.rs b/ferveo-common/src/keypair.rs index d30bcb74..4f1eccec 100644 --- a/ferveo-common/src/keypair.rs +++ b/ferveo-common/src/keypair.rs @@ -28,24 +28,6 @@ pub struct PublicKey { pub encryption_key: E::G2Affine, } -impl Default for PublicKey { - fn default() -> Self { - Self { - encryption_key: E::G2Affine::generator(), - } - } -} - -impl PublicKey { - pub fn to_bytes(&self) -> Result, bincode::Error> { - bincode::serialize(&self) - } - - pub fn from_bytes(bytes: &[u8]) -> Result { - bincode::deserialize(bytes) - } -} - #[serde_as] #[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct Keypair { @@ -70,12 +52,4 @@ impl Keypair { decryption_key: E::ScalarField::rand(rng), } } - - pub fn to_bytes(&self) -> Result, bincode::Error> { - bincode::serialize(&self) - } - - pub fn from_bytes(bytes: &[u8]) -> Result { - bincode::deserialize(bytes) - } } diff --git a/ferveo-common/src/serialization.rs b/ferveo-common/src/serialization.rs index d8953481..2107685f 100644 --- a/ferveo-common/src/serialization.rs +++ b/ferveo-common/src/serialization.rs @@ -3,6 +3,8 @@ //! Adapted from [o1-labs/proof-systems](https://raw.githubusercontent.com/o1-labs/proof-systems/31c76ceae3122f0ce09cded8260960ed5cbbe3d8/utils/src/serialization.rs). use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use serde; +use serde::{Deserialize, Serialize}; use serde_with::Bytes; // @@ -86,3 +88,45 @@ where .map_err(serde::de::Error::custom) } } + +// TODO: Trait aliases are experimental +// trait ByteSerializable = ToBytes + FromBytes; + +pub trait ToBytes { + fn to_bytes(&self) -> Result, bincode::Error>; +} + +pub trait FromBytes: Sized { + fn from_bytes(bytes: &[u8]) -> Result; +} + +impl ToBytes for T { + fn to_bytes(&self) -> Result, bincode::Error> { + bincode::serialize(self) + } +} + +impl Deserialize<'de>> FromBytes for T { + fn from_bytes(bytes: &[u8]) -> Result { + bincode::deserialize(bytes) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[derive(Serialize, Deserialize, Debug, PartialEq)] + struct Test { + a: u32, + b: u32, + } + + #[test] + fn test_serde() { + let test = Test { a: 1, b: 2 }; + let bytes = test.to_bytes().unwrap(); + let test2 = Test::from_bytes(&bytes).unwrap(); + assert_eq!(test, test2); + } +} diff --git a/ferveo-python/Cargo.toml b/ferveo-python/Cargo.toml index 0087014f..0cc8876d 100644 --- a/ferveo-python/Cargo.toml +++ b/ferveo-python/Cargo.toml @@ -9,6 +9,7 @@ crate-type = ["cdylib"] [dependencies] ferveo = { path = "../ferveo" } +ferveo-common = { path = "../ferveo-common" } pyo3 = { version = "0.17.3", features = ["macros"] } group-threshold-cryptography = { path = "../tpke" } derive_more = { version = "0.99", default-features = false, features = ["from", "as_ref"] } diff --git a/ferveo-python/src/lib.rs b/ferveo-python/src/lib.rs index 4bced028..1025cb63 100644 --- a/ferveo-python/src/lib.rs +++ b/ferveo-python/src/lib.rs @@ -1,11 +1,29 @@ extern crate alloc; +use std::fmt; + use ferveo::api::E; +use ferveo_common::serialization::{FromBytes, ToBytes}; use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::types::PyBytes; use rand::thread_rng; +fn from_py_bytes(bytes: &[u8]) -> PyResult { + T::from_bytes(bytes).map_err(map_py_error) +} + +fn to_py_bytes(t: T) -> PyResult { + let bytes = t.to_bytes().map_err(map_py_error)?; + Ok(Python::with_gil(|py| -> PyObject { + PyBytes::new(py, &bytes).into() + })) +} + +fn map_py_error(err: T) -> PyErr { + PyValueError::new_err(format!("{}", err)) +} + #[pyfunction] pub fn encrypt( message: &[u8], @@ -14,7 +32,7 @@ pub fn encrypt( ) -> PyResult { let rng = &mut thread_rng(); let ciphertext = ferveo::api::encrypt(message, aad, &public_key.0, rng) - .map_err(|err| PyValueError::new_err(format!("{}", err)))?; + .map_err(map_py_error)?; Ok(Ciphertext(ciphertext)) } @@ -62,21 +80,13 @@ impl Keypair { Self(ferveo::api::Keypair::new(&mut thread_rng())) } - // TODO: Consider moving from_bytes and __bytes__ to a separate trait - #[staticmethod] pub fn from_bytes(bytes: &[u8]) -> PyResult { - let keypair = ferveo::api::Keypair::from_bytes(bytes) - .map_err(|err| PyValueError::new_err(format!("{}", err)))?; - Ok(Self(keypair)) + from_py_bytes(bytes).map(Self) } fn __bytes__(&self) -> PyResult { - let serialized = self - .0 - .to_bytes() - .map_err(|err| PyValueError::new_err(format!("{}", err)))?; - Python::with_gil(|py| Ok(PyBytes::new(py, &serialized).into())) + to_py_bytes(self.0) } #[getter] @@ -93,17 +103,11 @@ pub struct PublicKey(ferveo::api::PublicKey); impl PublicKey { #[staticmethod] pub fn from_bytes(bytes: &[u8]) -> PyResult { - let pk = ferveo::api::PublicKey::from_bytes(bytes) - .map_err(|err| PyValueError::new_err(format!("{}", err)))?; - Ok(Self(pk)) + from_py_bytes(bytes).map(Self) } fn __bytes__(&self) -> PyResult { - let serialized = self - .0 - .to_bytes() - .map_err(|err| PyValueError::new_err(format!("{}", err)))?; - Python::with_gil(|py| Ok(PyBytes::new(py, &serialized).into())) + to_py_bytes(self.0) } } @@ -127,17 +131,11 @@ pub struct Transcript(ferveo::api::Transcript); impl Transcript { #[staticmethod] pub fn from_bytes(bytes: &[u8]) -> PyResult { - let transcript = ferveo::api::Transcript::from_bytes(bytes) - .map_err(|err| PyValueError::new_err(format!("{}", err)))?; - Ok(Self(transcript)) + from_py_bytes(bytes).map(Self) } fn __bytes__(&self) -> PyResult { - let serialized = self - .0 - .to_bytes() - .map_err(|err| PyValueError::new_err(format!("{}", err)))?; - Ok(Python::with_gil(|py| PyBytes::new(py, &serialized).into())) + to_py_bytes(&self.0) } } @@ -232,18 +230,11 @@ impl AggregatedTranscript { #[staticmethod] pub fn from_bytes(bytes: &[u8]) -> PyResult { - let aggregated_transcript = - ferveo::api::AggregatedTranscript::from_bytes(bytes) - .map_err(|err| PyValueError::new_err(format!("{}", err)))?; - Ok(Self(aggregated_transcript)) + from_py_bytes(bytes).map(Self) } fn __bytes__(&self) -> PyResult { - let serialized = self - .0 - .to_bytes() - .map_err(|err| PyValueError::new_err(format!("{}", err)))?; - Ok(Python::with_gil(|py| PyBytes::new(py, &serialized).into())) + to_py_bytes(&self.0) } } diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index 8090ea24..a29996c4 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -93,14 +93,6 @@ impl AggregatedTranscript { &dkg.0.pvss_params.g_inv(), ) } - - pub fn from_bytes(bytes: &[u8]) -> Result { - Ok(Self(bincode::deserialize(bytes)?)) - } - - pub fn to_bytes(&self) -> Result> { - Ok(bincode::serialize(&self.0)?) - } } #[cfg(test)] diff --git a/ferveo/src/vss/pvss.rs b/ferveo/src/vss/pvss.rs index 0489f580..f06883a5 100644 --- a/ferveo/src/vss/pvss.rs +++ b/ferveo/src/vss/pvss.rs @@ -189,14 +189,6 @@ impl PubliclyVerifiableSS { E::pairing(dkg.pvss_params.g, *y_i) == E::pairing(a_i, ek_i) }) } - - pub fn from_bytes(bytes: &[u8]) -> Result { - bincode::deserialize(bytes).map_err(|err| err.into()) - } - - pub fn to_bytes(&self) -> Result> { - bincode::serialize(&self).map_err(|err| err.into()) - } } /// Extra methods available to aggregated PVSS transcripts diff --git a/tpke-python/Cargo.toml b/tpke-python/Cargo.toml index 6d6b54fb..c94cffdd 100644 --- a/tpke-python/Cargo.toml +++ b/tpke-python/Cargo.toml @@ -10,6 +10,7 @@ crate-type = ["cdylib"] [dependencies] pyo3 = "0.17.3" group-threshold-cryptography = { path = "../tpke" } +ferveo-common = { path = "../ferveo-common" } [build-dependencies] pyo3-build-config = "*" diff --git a/tpke-python/src/lib.rs b/tpke-python/src/lib.rs index 7b270b8d..b3e20c6f 100644 --- a/tpke-python/src/lib.rs +++ b/tpke-python/src/lib.rs @@ -2,6 +2,7 @@ extern crate alloc; extern crate group_threshold_cryptography as tpke; +use ferveo_common::serialization::ToBytes; use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::types::PyBytes; diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index 91bfd09f..1dcbbfe6 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -3,6 +3,7 @@ extern crate group_threshold_cryptography as tpke; mod utils; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use ferveo_common::{FromBytes, ToBytes}; use js_sys::Error; use serde::{Deserialize, Serialize}; use serde_with::serde_as; @@ -11,6 +12,14 @@ use wasm_bindgen::prelude::*; extern crate wee_alloc; +fn to_js_bytes(t: &T) -> Result, Error> { + t.to_bytes().map_err(map_js_err) +} + +fn from_js_bytes(bytes: &[u8]) -> Result { + T::from_bytes(bytes).map_err(map_js_err) +} + #[wasm_bindgen] #[derive(Clone, Debug, PartialEq)] pub struct G1Prepared(tpke::api::G1Prepared); @@ -23,15 +32,12 @@ pub struct DecryptionShareSimple(tpke::api::DecryptionShareSimple); impl DecryptionShareSimple { #[wasm_bindgen] pub fn to_bytes(&self) -> Result, Error> { - self.0.to_bytes().map_err(map_js_err) + to_js_bytes(&self.0) } #[wasm_bindgen] pub fn from_bytes(bytes: &[u8]) -> Result { - let decryption_shares = - tpke::api::DecryptionShareSimple::from_bytes(bytes) - .map_err(map_js_err)?; - Ok(Self(decryption_shares)) + from_js_bytes(bytes).map(Self) } } @@ -45,17 +51,14 @@ pub struct DecryptionShareSimplePrecomputed( impl DecryptionShareSimplePrecomputed { #[wasm_bindgen] pub fn to_bytes(&self) -> Result, Error> { - self.0.to_bytes().map_err(map_js_err) + to_js_bytes(&self.0) } #[wasm_bindgen] pub fn from_bytes( bytes: &[u8], ) -> Result { - let decryption_share = - tpke::api::DecryptionShareSimplePrecomputed::from_bytes(bytes) - .map_err(map_js_err)?; - Ok(Self(decryption_share)) + from_js_bytes(bytes).map(Self) } } @@ -122,13 +125,11 @@ pub struct Ciphertext(tpke::api::Ciphertext); #[wasm_bindgen] impl Ciphertext { pub fn from_bytes(bytes: &[u8]) -> Result { - let ciphertext = - tpke::api::Ciphertext::from_bytes(bytes).map_err(map_js_err)?; - Ok(Ciphertext(ciphertext)) + from_js_bytes(bytes).map(Self) } pub fn to_bytes(&self) -> Result, Error> { - self.0.to_bytes().map_err(map_js_err) + to_js_bytes(&self.0) } } diff --git a/tpke/src/api.rs b/tpke/src/api.rs index 8d5a4b83..a0c06bfe 100644 --- a/tpke/src/api.rs +++ b/tpke/src/api.rs @@ -28,13 +28,3 @@ pub use crate::{ pub struct DomainPoint( #[serde_as(as = "serialization::SerdeAs")] pub ark_bls12_381::Fr, ); - -impl DomainPoint { - pub fn to_bytes(&self) -> Result> { - bincode::serialize(&self).map_err(|e| e.into()) - } - - pub fn from_bytes(bytes: &[u8]) -> Result { - bincode::deserialize(bytes).map_err(|e| e.into()) - } -} diff --git a/tpke/src/ciphertext.rs b/tpke/src/ciphertext.rs index 7dcb9cb9..dff76319 100644 --- a/tpke/src/ciphertext.rs +++ b/tpke/src/ciphertext.rs @@ -52,14 +52,6 @@ impl Ciphertext { + self.auth_tag.serialized_size(Compress::No) + self.ciphertext.len() } - - pub fn to_bytes(&self) -> Result> { - bincode::serialize(self).map_err(|err| err.into()) - } - - pub fn from_bytes(bytes: &[u8]) -> Result { - bincode::deserialize(bytes).map_err(|err| err.into()) - } } pub fn encrypt( @@ -217,29 +209,14 @@ fn construct_tag_hash( #[cfg(test)] mod tests { - use ark_bls12_381::G1Projective; - use ark_ec::CurveGroup; - use ark_std::{test_rng, UniformRand}; + + use ark_std::test_rng; use crate::test_common::*; use crate::*; type E = ark_bls12_381::Bls12_381; - #[test] - fn ciphertext_serialization() { - let rng = &mut test_rng(); - let msg: &[u8] = "abc".as_bytes(); - let aad: &[u8] = "my-aad".as_bytes(); - let pubkey = G1Projective::rand(rng).into_affine(); - - let ciphertext = encrypt::(msg, aad, &pubkey, rng).unwrap(); - let deserialized: Ciphertext = - Ciphertext::from_bytes(&ciphertext.to_bytes().unwrap()).unwrap(); - - assert_eq!(ciphertext, deserialized) - } - #[test] fn symmetric_encryption() { let rng = &mut test_rng(); diff --git a/tpke/src/decryption.rs b/tpke/src/decryption.rs index 1dbb17f5..ff1a7a26 100644 --- a/tpke/src/decryption.rs +++ b/tpke/src/decryption.rs @@ -23,16 +23,6 @@ pub struct DecryptionShareFast { pub decryption_share: E::G1Affine, } -impl DecryptionShareFast { - pub fn to_bytes(&self) -> Result> { - bincode::serialize(&self).map_err(|err| err.into()) - } - - pub fn from_bytes(bytes: &[u8]) -> Result { - bincode::deserialize(bytes).map_err(|err| err.into()) - } -} - #[serde_as] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ValidatorShareChecksum { @@ -82,14 +72,6 @@ impl ValidatorShareChecksum { true } - - pub fn from_bytes(bytes: &[u8]) -> Self { - bincode::deserialize(bytes).unwrap() - } - - pub fn to_bytes(&self) -> Vec { - bincode::serialize(&self).unwrap() - } } #[serde_as] @@ -166,14 +148,6 @@ impl DecryptionShareSimple { ciphertext, ) } - - pub fn from_bytes(bytes: &[u8]) -> Result { - bincode::deserialize(bytes).map_err(|err| err.into()) - } - - pub fn to_bytes(&self) -> Result> { - bincode::serialize(&self).map_err(|err| err.into()) - } } #[serde_as] @@ -252,14 +226,6 @@ impl DecryptionShareSimplePrecomputed { ciphertext, ) } - - pub fn from_bytes(bytes: &[u8]) -> Result { - bincode::deserialize(bytes).map_err(|e| e.into()) - } - - pub fn to_bytes(&self) -> Result> { - bincode::serialize(self).map_err(|e| e.into()) - } } // TODO: Remove this code? Currently only used in benchmarks. Move to benchmark suite? @@ -395,6 +361,7 @@ pub fn verify_decryption_shares_simple( #[cfg(test)] mod tests { use ark_ec::AffineRepr; + use ferveo_common::{FromBytes, ToBytes}; use crate::*; diff --git a/tpke/src/lib.rs b/tpke/src/lib.rs index d0231a42..62a54b25 100644 --- a/tpke/src/lib.rs +++ b/tpke/src/lib.rs @@ -282,6 +282,7 @@ mod tests { use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::Zero; use ark_std::{test_rng, UniformRand}; + use ferveo_common::{FromBytes, ToBytes}; use rand_core::RngCore; use crate::refresh::{ From c8f9f57a0e9e9da06d24cdde5e0bf379cb5e671e Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Mon, 20 Feb 2023 15:53:49 +0100 Subject: [PATCH 29/36] add tpke-wasm api example --- tpke-wasm/examples/node/.gitignore | 10 + tpke-wasm/examples/node/README.md | 10 + tpke-wasm/examples/node/package.json | 49 + tpke-wasm/examples/node/src/main.test.ts | 84 + tpke-wasm/examples/node/src/main.ts | 5 + tpke-wasm/examples/node/tsconfig.json | 27 + tpke-wasm/examples/node/yarn.lock | 3366 ++++++++++++++++++++++ tpke-wasm/src/lib.rs | 47 +- tpke-wasm/src/utils.rs | 9 + tpke-wasm/tests/node.rs | 4 +- 10 files changed, 3582 insertions(+), 29 deletions(-) create mode 100644 tpke-wasm/examples/node/.gitignore create mode 100644 tpke-wasm/examples/node/README.md create mode 100644 tpke-wasm/examples/node/package.json create mode 100644 tpke-wasm/examples/node/src/main.test.ts create mode 100644 tpke-wasm/examples/node/src/main.ts create mode 100644 tpke-wasm/examples/node/tsconfig.json create mode 100644 tpke-wasm/examples/node/yarn.lock diff --git a/tpke-wasm/examples/node/.gitignore b/tpke-wasm/examples/node/.gitignore new file mode 100644 index 00000000..a37ab157 --- /dev/null +++ b/tpke-wasm/examples/node/.gitignore @@ -0,0 +1,10 @@ +/node_modules/ +/build/ +/lib/ +/dist/ +/docs/ +.idea/* + +.DS_Store +coverage +*.log diff --git a/tpke-wasm/examples/node/README.md b/tpke-wasm/examples/node/README.md new file mode 100644 index 00000000..44878d8b --- /dev/null +++ b/tpke-wasm/examples/node/README.md @@ -0,0 +1,10 @@ +# `tpke-wasm` in Node.js: + +## Usage + +```bash +$ yarn install +$ yarn test +``` + +Inspect console output for results. diff --git a/tpke-wasm/examples/node/package.json b/tpke-wasm/examples/node/package.json new file mode 100644 index 00000000..cd7278ad --- /dev/null +++ b/tpke-wasm/examples/node/package.json @@ -0,0 +1,49 @@ +{ + "name": "tpke-wasm", + "version": "0.1.0", + "description": "A usage example for tpke-wasm", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "/dist" + ], + "scripts": { + "start": "ts-node src/main.ts", + "test": "jest", + "test:watch": "jest --watchAll", + "lint": "eslint src/ --ext .js,.jsx,.ts,.tsx", + "build": "tsc -p tsconfig.json", + "clean": "rm -rf dist build", + "ts-node": "ts-node" + }, + "collaborators": [ + "Piotr Rosłaniec " + ], + "license": "GPL-3.0-only", + "dependencies": { + "tpke-wasm": "file:../../pkg" + }, + "devDependencies": { + "@babel/preset-typescript": "^7.16.5", + "@types/jest": "^27.0.3", + "@types/mocha": "^9.0.0", + "@types/node": "^17.0.0", + "@typescript-eslint/eslint-plugin": "^5.7.0", + "@typescript-eslint/parser": "^5.7.0", + "eslint": "^8.4.1", + "jest": "^27.4.5", + "ts-jest": "^27.1.1", + "ts-node": "^10.4.0", + "typescript": "^4.5.4" + }, + "jest": { + "preset": "ts-jest", + "testEnvironment": "node", + "transform": { + "node_modules/variables/.+\\.(j|t)sx?$": "ts-jest" + }, + "transformIgnorePatterns": [ + "node_modules/(?!variables/.*)" + ] + } +} diff --git a/tpke-wasm/examples/node/src/main.test.ts b/tpke-wasm/examples/node/src/main.test.ts new file mode 100644 index 00000000..4110b5d0 --- /dev/null +++ b/tpke-wasm/examples/node/src/main.test.ts @@ -0,0 +1,84 @@ +import { + Ciphertext, + decryptWithSharedSecret, + Dkg, + encrypt, + SharedSecretSimpleBuilder, + DecryptionShareSimple, +} from "tpke-wasm"; + +const zip = (a: Array, b: Array) => a.map((k: T, i: number) => [k, b[i]]); + +// This test suite replicates tests from tpke-wasm/tests/node.rs +describe("tpke", () => { + it("performs simple tdec", () => { + const sharesNum = 16; + const threshold = (sharesNum * 2) / 3; + const msg = Buffer.from("my-msg"); + const aad = Buffer.from("my-aad"); + + const dkg = new Dkg(threshold, sharesNum); + + // + // On the client side + // + + // Encrypt the message + const ciphertext = encrypt(msg, aad, dkg.public_key); + + // Serialize and send to validators + const ciphertext_bytes = ciphertext.toBytes(); + + // + // On the server side + // + + const ciphertext2 = Ciphertext.fromBytes(ciphertext_bytes); + expect(ciphertext2.toBytes()).toEqual(ciphertext.toBytes()); + + // Create decryption shares + + const decryptionShares = []; + for (let i = 0; i < threshold; i++) { + const share = dkg.makeDecryptionShareSimple(ciphertext, aad, i); + decryptionShares.push(share); + } + + const domainPoints = []; + for (let i = 0; i < threshold; i++) { + const point = dkg.getDomainPoint(i); + domainPoints.push(point); + } + + // Serialize and send back to client + const decryptionSharesBytes = decryptionShares.map((s) => s.toBytes()); + + // + // On the client side + // + + const decryptionShares2 = decryptionSharesBytes.map((b) => + DecryptionShareSimple.fromBytes(b) + ); + zip(decryptionShares, decryptionShares2).map(([s1, s2]) => + expect(s1.toBytes()).toEqual(s2.toBytes()) + ) + + // Combine shares into a shared secret + const ssBuilder = new SharedSecretSimpleBuilder(threshold); + decryptionShares.forEach((share) => ssBuilder.addDecryptionShare(share)); + + domainPoints.forEach((point) => ssBuilder.addDomainPoint(point)); + + const shared_secret = ssBuilder.build(); + + // Decrypt the message + const plaintext = decryptWithSharedSecret( + ciphertext, + aad, + shared_secret, + dkg.gInv + ); + expect(Buffer.from(plaintext)).toEqual(msg); + }); +}); diff --git a/tpke-wasm/examples/node/src/main.ts b/tpke-wasm/examples/node/src/main.ts new file mode 100644 index 00000000..f035feb3 --- /dev/null +++ b/tpke-wasm/examples/node/src/main.ts @@ -0,0 +1,5 @@ +function run() { + console.log("Success!"); +} + +run(); diff --git a/tpke-wasm/examples/node/tsconfig.json b/tpke-wasm/examples/node/tsconfig.json new file mode 100644 index 00000000..ab515b5a --- /dev/null +++ b/tpke-wasm/examples/node/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "moduleResolution": "node", + "declaration": true, + "strict": true, + "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */, + "strictNullChecks": true /* Enable strict null checks. */, + "strictFunctionTypes": true /* Enable strict checking of function types. */, + "noUnusedLocals": true /* Report errors on unused locals. */, + "noUnusedParameters": true /* Report errors on unused parameters. */, + "noImplicitReturns": true /* Report error when not all code paths in function return a value. */, + "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */, + "importHelpers": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "sourceMap": true, + "outDir": "./dist/tsc/", + "types": ["node", "jest"], + "lib": ["ES6", "DOM"] + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "**/*.test.ts"] +} diff --git a/tpke-wasm/examples/node/yarn.lock b/tpke-wasm/examples/node/yarn.lock new file mode 100644 index 00000000..d981f24e --- /dev/null +++ b/tpke-wasm/examples/node/yarn.lock @@ -0,0 +1,3366 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + dependencies: + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.20.5": + version "7.20.14" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.14.tgz#4106fc8b755f3e3ee0a0a7c27dde5de1d2b2baf8" + integrity sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw== + +"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.7.2", "@babel/core@^7.8.0": + version "7.20.12" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.12.tgz#7930db57443c6714ad216953d1356dac0eb8496d" + integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.7" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-module-transforms" "^7.20.11" + "@babel/helpers" "^7.20.7" + "@babel/parser" "^7.20.7" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.12" + "@babel/types" "^7.20.7" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.2" + semver "^6.3.0" + +"@babel/generator@^7.20.7", "@babel/generator@^7.7.2": + version "7.20.14" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.14.tgz#9fa772c9f86a46c6ac9b321039400712b96f64ce" + integrity sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg== + dependencies: + "@babel/types" "^7.20.7" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-compilation-targets@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz#a6cd33e93629f5eb473b021aac05df62c4cd09bb" + integrity sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ== + dependencies: + "@babel/compat-data" "^7.20.5" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.21.3" + lru-cache "^5.1.1" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.20.12": + version "7.20.12" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.12.tgz#4349b928e79be05ed2d1643b20b99bb87c503819" + integrity sha512-9OunRkbT0JQcednL0UFvbfXpAsUXiGjUk0a7sN8fUXX7Mue79cUSMjHGDRRi/Vz9vYlpIhLV5fMD5dKoMhhsNQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-member-expression-to-functions" "^7.20.7" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.20.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" + "@babel/helper-split-export-declaration" "^7.18.6" + +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== + +"@babel/helper-function-name@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== + dependencies: + "@babel/template" "^7.18.10" + "@babel/types" "^7.19.0" + +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-member-expression-to-functions@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz#a6f26e919582275a93c3aa6594756d71b0bb7f05" + integrity sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw== + dependencies: + "@babel/types" "^7.20.7" + +"@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.20.11": + version "7.20.11" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0" + integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.10" + "@babel/types" "^7.20.7" + +"@babel/helper-optimise-call-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" + integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== + +"@babel/helper-replace-supers@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz#243ecd2724d2071532b2c8ad2f0f9f083bcae331" + integrity sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-member-expression-to-functions" "^7.20.7" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.7" + "@babel/types" "^7.20.7" + +"@babel/helper-simple-access@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" + integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== + dependencies: + "@babel/types" "^7.20.2" + +"@babel/helper-skip-transparent-expression-wrappers@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" + integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== + dependencies: + "@babel/types" "^7.20.0" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== + +"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helpers@^7.20.7": + version "7.20.13" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.13.tgz#e3cb731fb70dc5337134cadc24cbbad31cc87ad2" + integrity sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg== + dependencies: + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.13" + "@babel/types" "^7.20.7" + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.13", "@babel/parser@^7.20.7": + version "7.20.15" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.15.tgz#eec9f36d8eaf0948bb88c87a46784b5ee9fd0c89" + integrity sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.20.0", "@babel/plugin-syntax-typescript@^7.7.2": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + +"@babel/plugin-transform-typescript@^7.18.6": + version "7.20.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.13.tgz#e3581b356b8694f6ff450211fe6774eaff8d25ab" + integrity sha512-O7I/THxarGcDZxkgWKMUrk7NK1/WbHAg3Xx86gqS6x9MTrNL6AwIluuZ96ms4xeDe6AVx6rjHbWHP7x26EPQBA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.20.12" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-typescript" "^7.20.0" + +"@babel/preset-typescript@^7.16.5": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" + integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-typescript" "^7.18.6" + +"@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.3.3": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" + integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + +"@babel/traverse@^7.20.10", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.13", "@babel/traverse@^7.20.7", "@babel/traverse@^7.7.2": + version "7.20.13" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.13.tgz#817c1ba13d11accca89478bd5481b2d168d07473" + integrity sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.7" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.20.13" + "@babel/types" "^7.20.7" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" + integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@eslint/eslintrc@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" + integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.4.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@humanwhocodes/config-array@^0.11.8": + version "0.11.8" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" + integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba" + integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^27.5.1" + jest-util "^27.5.1" + slash "^3.0.0" + +"@jest/core@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626" + integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ== + dependencies: + "@jest/console" "^27.5.1" + "@jest/reporters" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.8.1" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^27.5.1" + jest-config "^27.5.1" + jest-haste-map "^27.5.1" + jest-message-util "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-resolve-dependencies "^27.5.1" + jest-runner "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + jest-watcher "^27.5.1" + micromatch "^4.0.4" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74" + integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA== + dependencies: + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + +"@jest/fake-timers@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" + integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ== + dependencies: + "@jest/types" "^27.5.1" + "@sinonjs/fake-timers" "^8.0.1" + "@types/node" "*" + jest-message-util "^27.5.1" + jest-mock "^27.5.1" + jest-util "^27.5.1" + +"@jest/globals@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b" + integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/types" "^27.5.1" + expect "^27.5.1" + +"@jest/reporters@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04" + integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^5.1.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-haste-map "^27.5.1" + jest-resolve "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^4.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^8.1.0" + +"@jest/source-map@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" + integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.2.9" + source-map "^0.6.0" + +"@jest/test-result@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb" + integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag== + dependencies: + "@jest/console" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b" + integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ== + dependencies: + "@jest/test-result" "^27.5.1" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-runtime "^27.5.1" + +"@jest/transform@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409" + integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^27.5.1" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-regex-util "^27.5.1" + jest-util "^27.5.1" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" + integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@sinonjs/commons@^1.7.0": + version "1.8.6" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" + integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^8.0.1": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7" + integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.0.tgz#61bc5a4cae505ce98e1e36c5445e4bee060d8891" + integrity sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" + integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": + version "7.18.3" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.3.tgz#dfc508a85781e5698d5b33443416b6268c4b3e8d" + integrity sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w== + dependencies: + "@babel/types" "^7.3.0" + +"@types/graceful-fs@^4.1.2": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.6.tgz#e14b2576a1c25026b7f02ede1de3b84c3a1efeae" + integrity sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^27.0.3": + version "27.5.2" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.5.2.tgz#ec49d29d926500ffb9fd22b84262e862049c026c" + integrity sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA== + dependencies: + jest-matcher-utils "^27.0.0" + pretty-format "^27.0.0" + +"@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/mocha@^9.0.0": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== + +"@types/node@*": + version "18.14.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.0.tgz#94c47b9217bbac49d4a67a967fdcdeed89ebb7d0" + integrity sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A== + +"@types/node@^17.0.0": + version "17.0.45" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" + integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== + +"@types/prettier@^2.1.5": + version "2.7.2" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" + integrity sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg== + +"@types/semver@^7.3.12": + version "7.3.13" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" + integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== + +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^16.0.0": + version "16.0.5" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.5.tgz#12cc86393985735a283e387936398c2f9e5f88e3" + integrity sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@^5.7.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz#5fb0d43574c2411f16ea80f5fc335b8eaa7b28a8" + integrity sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg== + dependencies: + "@typescript-eslint/scope-manager" "5.52.0" + "@typescript-eslint/type-utils" "5.52.0" + "@typescript-eslint/utils" "5.52.0" + debug "^4.3.4" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + regexpp "^3.2.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.7.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.52.0.tgz#73c136df6c0133f1d7870de7131ccf356f5be5a4" + integrity sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA== + dependencies: + "@typescript-eslint/scope-manager" "5.52.0" + "@typescript-eslint/types" "5.52.0" + "@typescript-eslint/typescript-estree" "5.52.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.52.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz#a993d89a0556ea16811db48eabd7c5b72dcb83d1" + integrity sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw== + dependencies: + "@typescript-eslint/types" "5.52.0" + "@typescript-eslint/visitor-keys" "5.52.0" + +"@typescript-eslint/type-utils@5.52.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz#9fd28cd02e6f21f5109e35496df41893f33167aa" + integrity sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw== + dependencies: + "@typescript-eslint/typescript-estree" "5.52.0" + "@typescript-eslint/utils" "5.52.0" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.52.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.52.0.tgz#19e9abc6afb5bd37a1a9bea877a1a836c0b3241b" + integrity sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ== + +"@typescript-eslint/typescript-estree@5.52.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz#6408cb3c2ccc01c03c278cb201cf07e73347dfca" + integrity sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ== + dependencies: + "@typescript-eslint/types" "5.52.0" + "@typescript-eslint/visitor-keys" "5.52.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.52.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.52.0.tgz#b260bb5a8f6b00a0ed51db66bdba4ed5e4845a72" + integrity sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA== + dependencies: + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.52.0" + "@typescript-eslint/types" "5.52.0" + "@typescript-eslint/typescript-estree" "5.52.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + semver "^7.3.7" + +"@typescript-eslint/visitor-keys@5.52.0": + version "5.52.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz#e38c971259f44f80cfe49d97dbffa38e3e75030f" + integrity sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA== + dependencies: + "@typescript-eslint/types" "5.52.0" + eslint-visitor-keys "^3.3.0" + +abab@^2.0.3, abab@^2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== + +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^7.1.1: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +acorn@^8.2.4, acorn@^8.4.1, acorn@^8.8.0: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +babel-jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" + integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg== + dependencies: + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^27.5.1" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e" + integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81" + integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag== + dependencies: + babel-plugin-jest-hoist "^27.5.1" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + +browserslist@^4.21.3: + version "4.21.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" + integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== + dependencies: + caniuse-lite "^1.0.30001449" + electron-to-chromium "^1.4.284" + node-releases "^2.0.8" + update-browserslist-db "^1.0.10" + +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001449: + version "1.0.30001457" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz#6af34bb5d720074e2099432aa522c21555a18301" + integrity sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA== + +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +ci-info@^3.2.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" + integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== + +cjs-module-lexer@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" + integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decimal.js@^10.2.1: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== + +deep-is@^0.1.3, deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^4.2.2: + version "4.3.0" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.0.tgz#65491893ec47756d44719ae520e0e2609233b59b" + integrity sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff-sequences@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" + integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + +electron-to-chromium@^1.4.284: + version "1.4.302" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.302.tgz#5770646ffe7051677b489226144aad9386d420f2" + integrity sha512-Uk7C+7aPBryUR1Fwvk9VmipBcN9fVsqBO57jV2ZjTm+IZ6BMNqu7EDVEg2HxCNufk6QcWlFsBkhQyQroB2VWKw== + +emittery@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" + integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" + integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== + +eslint@^8.4.1: + version "8.34.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.34.0.tgz#fe0ab0ef478104c1f9ebc5537e303d25a8fb22d6" + integrity sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg== + dependencies: + "@eslint/eslintrc" "^1.4.1" + "@humanwhocodes/config-array" "^0.11.8" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.4.0" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-sdsl "^4.1.4" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + +espree@^9.4.0: + version "9.4.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" + integrity sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg== + dependencies: + acorn "^8.8.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.3.0" + +esprima@^4.0.0, esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.0: + version "1.4.2" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.2.tgz#c6d3fee05dd665808e2ad870631f221f5617b1d1" + integrity sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74" + integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw== + dependencies: + "@jest/types" "^27.5.1" + jest-get-type "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.19.0: + version "13.20.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" + integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" + integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw== + dependencies: + "@jest/types" "^27.5.1" + execa "^5.0.0" + throat "^6.0.1" + +jest-circus@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc" + integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^0.7.0" + expect "^27.5.1" + is-generator-fn "^2.0.0" + jest-each "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + slash "^3.0.0" + stack-utils "^2.0.3" + throat "^6.0.1" + +jest-cli@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145" + integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw== + dependencies: + "@jest/core" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + import-local "^3.0.2" + jest-config "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + prompts "^2.0.1" + yargs "^16.2.0" + +jest-config@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41" + integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA== + dependencies: + "@babel/core" "^7.8.0" + "@jest/test-sequencer" "^27.5.1" + "@jest/types" "^27.5.1" + babel-jest "^27.5.1" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.1" + graceful-fs "^4.2.9" + jest-circus "^27.5.1" + jest-environment-jsdom "^27.5.1" + jest-environment-node "^27.5.1" + jest-get-type "^27.5.1" + jest-jasmine2 "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-runner "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^27.5.1" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" + integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-docblock@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0" + integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ== + dependencies: + detect-newline "^3.0.0" + +jest-each@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e" + integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ== + dependencies: + "@jest/types" "^27.5.1" + chalk "^4.0.0" + jest-get-type "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + +jest-environment-jsdom@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546" + integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + jest-util "^27.5.1" + jsdom "^16.6.0" + +jest-environment-node@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e" + integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + jest-util "^27.5.1" + +jest-get-type@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" + integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== + +jest-haste-map@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" + integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng== + dependencies: + "@jest/types" "^27.5.1" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^27.5.1" + jest-serializer "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + micromatch "^4.0.4" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + +jest-jasmine2@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" + integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/source-map" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + expect "^27.5.1" + is-generator-fn "^2.0.0" + jest-each "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + throat "^6.0.1" + +jest-leak-detector@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8" + integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ== + dependencies: + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" + integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== + dependencies: + chalk "^4.0.0" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-message-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" + integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^27.5.1" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^27.5.1" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6" + integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" + integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== + +jest-resolve-dependencies@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" + integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg== + dependencies: + "@jest/types" "^27.5.1" + jest-regex-util "^27.5.1" + jest-snapshot "^27.5.1" + +jest-resolve@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384" + integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw== + dependencies: + "@jest/types" "^27.5.1" + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-pnp-resolver "^1.2.2" + jest-util "^27.5.1" + jest-validate "^27.5.1" + resolve "^1.20.0" + resolve.exports "^1.1.0" + slash "^3.0.0" + +jest-runner@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5" + integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ== + dependencies: + "@jest/console" "^27.5.1" + "@jest/environment" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.8.1" + graceful-fs "^4.2.9" + jest-docblock "^27.5.1" + jest-environment-jsdom "^27.5.1" + jest-environment-node "^27.5.1" + jest-haste-map "^27.5.1" + jest-leak-detector "^27.5.1" + jest-message-util "^27.5.1" + jest-resolve "^27.5.1" + jest-runtime "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + source-map-support "^0.5.6" + throat "^6.0.1" + +jest-runtime@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af" + integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/globals" "^27.5.1" + "@jest/source-map" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + execa "^5.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-message-util "^27.5.1" + jest-mock "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-serializer@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64" + integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.9" + +jest-snapshot@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1" + integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA== + dependencies: + "@babel/core" "^7.7.2" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.0.0" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/babel__traverse" "^7.0.4" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^27.5.1" + graceful-fs "^4.2.9" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + jest-haste-map "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-util "^27.5.1" + natural-compare "^1.4.0" + pretty-format "^27.5.1" + semver "^7.3.2" + +jest-util@^27.0.0, jest-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" + integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" + integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ== + dependencies: + "@jest/types" "^27.5.1" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^27.5.1" + leven "^3.1.0" + pretty-format "^27.5.1" + +jest-watcher@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2" + integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw== + dependencies: + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + jest-util "^27.5.1" + string-length "^4.0.1" + +jest-worker@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc" + integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ== + dependencies: + "@jest/core" "^27.5.1" + import-local "^3.0.2" + jest-cli "^27.5.1" + +js-sdsl@^4.1.4: + version "4.3.0" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.3.0.tgz#aeefe32a451f7af88425b11fdb5f58c90ae1d711" + integrity sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsdom@^16.6.0: + version "16.7.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" + integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== + dependencies: + abab "^2.0.5" + acorn "^8.2.4" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.3.0" + data-urls "^2.0.0" + decimal.js "^10.2.1" + domexception "^2.0.1" + escodegen "^2.0.0" + form-data "^3.0.0" + html-encoding-sniffer "^2.0.1" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.0" + parse5 "6.0.1" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.5.0" + ws "^7.4.6" + xml-name-validator "^3.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@2.x, json5@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash@^4.7.0: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-error@1.x, make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.8: + version "2.0.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" + integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +nwsapi@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0" + integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse5@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pirates@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + +pretty-format@^27.0.0, pretty-format@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +psl@^1.1.33: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve.exports@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.1.tgz#05cfd5b3edf641571fd46fa608b610dda9ead999" + integrity sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ== + +resolve@^1.20.0: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +saxes@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + +semver@7.x, semver@^7.3.2, semver@^7.3.7: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + +semver@^6.0.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.2, signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +source-map-support@^0.5.6: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.3: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-hyperlinks@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" + integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +throat@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.2.tgz#51a3fbb5e11ae72e2cf74861ed5c8020f89f29fe" + integrity sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ== + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tough-cookie@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" + integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + +"tpke-wasm@file:../../pkg": + version "0.1.0" + +tr46@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" + integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== + dependencies: + punycode "^2.1.1" + +ts-jest@^27.1.1: + version "27.1.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-27.1.5.tgz#0ddf1b163fbaae3d5b7504a1e65c914a95cff297" + integrity sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^27.0.0" + json5 "2.x" + lodash.memoize "4.x" + make-error "1.x" + semver "7.x" + yargs-parser "20.x" + +ts-node@^10.4.0: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typescript@^4.5.4: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + +update-browserslist-db@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +v8-to-istanbul@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" + integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + +walker@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^8.0.0, whatwg-url@^8.5.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" + integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== + dependencies: + lodash "^4.7.0" + tr46 "^2.1.0" + webidl-conversions "^6.1.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.3, word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@^7.4.6: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@20.x, yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index 1dcbbfe6..93028fe9 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -3,7 +3,6 @@ extern crate group_threshold_cryptography as tpke; mod utils; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; -use ferveo_common::{FromBytes, ToBytes}; use js_sys::Error; use serde::{Deserialize, Serialize}; use serde_with::serde_as; @@ -12,14 +11,6 @@ use wasm_bindgen::prelude::*; extern crate wee_alloc; -fn to_js_bytes(t: &T) -> Result, Error> { - t.to_bytes().map_err(map_js_err) -} - -fn from_js_bytes(bytes: &[u8]) -> Result { - T::from_bytes(bytes).map_err(map_js_err) -} - #[wasm_bindgen] #[derive(Clone, Debug, PartialEq)] pub struct G1Prepared(tpke::api::G1Prepared); @@ -30,12 +21,12 @@ pub struct DecryptionShareSimple(tpke::api::DecryptionShareSimple); #[wasm_bindgen] impl DecryptionShareSimple { - #[wasm_bindgen] + #[wasm_bindgen(js_name = "toBytes")] pub fn to_bytes(&self) -> Result, Error> { to_js_bytes(&self.0) } - #[wasm_bindgen] + #[wasm_bindgen(js_name = "fromBytes")] pub fn from_bytes(bytes: &[u8]) -> Result { from_js_bytes(bytes).map(Self) } @@ -49,12 +40,12 @@ pub struct DecryptionShareSimplePrecomputed( #[wasm_bindgen] impl DecryptionShareSimplePrecomputed { - #[wasm_bindgen] + #[wasm_bindgen(js_name = "toBytes")] pub fn to_bytes(&self) -> Result, Error> { to_js_bytes(&self.0) } - #[wasm_bindgen] + #[wasm_bindgen(js_name = "fromBytes")] pub fn from_bytes( bytes: &[u8], ) -> Result { @@ -72,7 +63,7 @@ pub struct PublicKey( #[wasm_bindgen] impl PublicKey { - #[wasm_bindgen] + #[wasm_bindgen(js_name = "fromBytes")] pub fn from_bytes(bytes: &[u8]) -> Result { let mut reader = bytes; let pk = tpke::api::DkgPublicKey::deserialize_uncompressed(&mut reader) @@ -80,7 +71,7 @@ impl PublicKey { Ok(PublicKey(pk)) } - #[wasm_bindgen] + #[wasm_bindgen(js_name = "toBytes")] pub fn to_bytes(&self) -> Result, Error> { let mut bytes = Vec::new(); self.0 @@ -100,7 +91,7 @@ pub struct PrivateKey( #[wasm_bindgen] impl PrivateKey { - #[wasm_bindgen] + #[wasm_bindgen(js_name = "fromBytes")] pub fn from_bytes(bytes: &[u8]) -> Result { let mut reader = bytes; let pk = tpke::api::PrivateKey::deserialize_uncompressed(&mut reader) @@ -108,7 +99,7 @@ impl PrivateKey { Ok(PrivateKey(pk)) } - #[wasm_bindgen] + #[wasm_bindgen(js_name = "toBytes")] pub fn to_bytes(&self) -> Result, Error> { let mut bytes = Vec::new(); self.0 @@ -124,10 +115,12 @@ pub struct Ciphertext(tpke::api::Ciphertext); #[wasm_bindgen] impl Ciphertext { + #[wasm_bindgen(js_name = "fromBytes")] pub fn from_bytes(bytes: &[u8]) -> Result { from_js_bytes(bytes).map(Self) } + #[wasm_bindgen(js_name = "toBytes")] pub fn to_bytes(&self) -> Result, Error> { to_js_bytes(&self.0) } @@ -146,7 +139,7 @@ pub fn encrypt( Ok(Ciphertext(ciphertext)) } -#[wasm_bindgen] +#[wasm_bindgen(js_name = "decryptWithPrivateKey")] pub fn decrypt_with_private_key( ciphertext: &Ciphertext, aad: &[u8], @@ -183,7 +176,7 @@ impl SharedSecretPrecomputedBuilder { } } - #[wasm_bindgen] + #[wasm_bindgen(js_name = "addDecryptionShare")] pub fn add_decryption_share( &mut self, share: &DecryptionShareSimplePrecomputed, @@ -220,12 +213,12 @@ impl SharedSecretSimpleBuilder { } } - #[wasm_bindgen] + #[wasm_bindgen(js_name = "addDecryptionShare")] pub fn add_decryption_share(&mut self, share: &DecryptionShareSimple) { self.shares.push(share.0.clone()); } - #[wasm_bindgen] + #[wasm_bindgen(js_name = "addDomainPoint")] pub fn add_domain_point(&mut self, domain_point: &DomainPoint) { self.domain_points.push(domain_point.0.clone()); } @@ -244,7 +237,7 @@ impl SharedSecretSimpleBuilder { } } -#[wasm_bindgen] +#[wasm_bindgen(js_name = "decryptWithSharedSecret")] pub fn decrypt_with_shared_secret( ciphertext: &Ciphertext, aad: &[u8], @@ -291,7 +284,7 @@ pub mod test_common { } } - #[wasm_bindgen] + #[wasm_bindgen(js_name = "makeDecryptionShareSimple")] pub fn make_decryption_share_simple( &self, ciphertext: &Ciphertext, @@ -306,7 +299,7 @@ pub mod test_common { )) } - #[wasm_bindgen] + #[wasm_bindgen(js_name = "makeDecryptionSharePrecomputed")] pub fn make_decryption_share_precomputed( &self, ciphertext: &Ciphertext, @@ -321,8 +314,8 @@ pub mod test_common { )) } - #[wasm_bindgen] - pub fn domain_point(&self, validator_index: usize) -> DomainPoint { + #[wasm_bindgen(js_name = "getDomainPoint")] + pub fn get_domain_point(&self, validator_index: usize) -> DomainPoint { set_panic_hook(); DomainPoint(tpke::api::DomainPoint( self.private_contexts[0].public_decryption_contexts @@ -331,7 +324,7 @@ pub mod test_common { )) } - #[wasm_bindgen(getter)] + #[wasm_bindgen(getter, js_name = "gInv")] pub fn g_inv(&self) -> G1Prepared { set_panic_hook(); G1Prepared(self.private_contexts[0].setup_params.g_inv.clone()) diff --git a/tpke-wasm/src/utils.rs b/tpke-wasm/src/utils.rs index 1292d393..91858903 100644 --- a/tpke-wasm/src/utils.rs +++ b/tpke-wasm/src/utils.rs @@ -1,5 +1,6 @@ use core::fmt; +use ferveo_common::{FromBytes, ToBytes}; use js_sys::Error; pub fn set_panic_hook() { @@ -16,3 +17,11 @@ pub fn set_panic_hook() { pub fn map_js_err(err: T) -> Error { Error::new(&format!("{}", err)) } + +pub fn to_js_bytes(t: &T) -> Result, Error> { + t.to_bytes().map_err(map_js_err) +} + +pub fn from_js_bytes(bytes: &[u8]) -> Result { + T::from_bytes(bytes).map_err(map_js_err) +} diff --git a/tpke-wasm/tests/node.rs b/tpke-wasm/tests/node.rs index 1ec52aee..d76fd4c5 100644 --- a/tpke-wasm/tests/node.rs +++ b/tpke-wasm/tests/node.rs @@ -12,7 +12,7 @@ use wasm_bindgen_test::*; fn tdec_simple() { let shares_num = 16; let threshold = shares_num * 2 / 3; - let msg = "abc".as_bytes().to_vec(); + let msg = "my-msg".as_bytes().to_vec(); let aad = "my-aad".as_bytes().to_vec(); let dkg = Dkg::new(threshold, shares_num); @@ -44,7 +44,7 @@ fn tdec_simple() { .collect::>(); let domain_points = (0..threshold) - .map(|i| dkg.domain_point(i)) + .map(|i| dkg.get_domain_point(i)) .collect::>(); // Serialize and send back to client From 13175933ff30bb64d546c061ef18106271fa2cb5 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Mon, 20 Feb 2023 15:56:23 +0100 Subject: [PATCH 30/36] add yarn test to ci --- .github/workflows/workspace.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index fa695c91..edbc0f52 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -108,6 +108,35 @@ jobs: - run: cargo install wasm-pack - run: wasm-pack test --node working-directory: tpke-wasm + + yarn-test: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + target: + - wasm32-unknown-unknown + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + target: ${{ matrix.target }} + override: true + - run: cargo install wasm-pack + - run: wasm-pack build --target nodejs + working-directory: tpke-wasm + - uses: borales/actions-yarn@v3.0.0 + with: + cmd: --cwd tpke-wasm/examples/node install + - uses: borales/actions-yarn@v3.0.0 + with: + cmd: --cwd tpke-wasm/examples/node build + - uses: borales/actions-yarn@v3.0.0 + with: + cmd: --cwd tpke-wasm/examples/node test codecov: runs-on: ubuntu-latest From af9505d277eb43760698c5677d2cc0583d6484f4 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Tue, 21 Feb 2023 10:16:40 +0100 Subject: [PATCH 31/36] fix benchmarks not running on ci --- .github/workflows/workspace.yml | 4 +++- ferveo/Cargo.toml | 6 ++++++ tpke/Cargo.toml | 9 ++++----- tpke/benches/arkworks.rs | 34 ++++++++++++++++++++------------- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index edbc0f52..446ab2ef 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -189,10 +189,12 @@ jobs: restore-keys: ${{ runner.os }}-cargo- - name: Run benchmark for base branch comparison uses: boa-dev/criterion-compare-action@v3 - if: github.event_name == 'pull_request' + # Only PRs to main + if: github.event_name == 'pull_request' && github.ref == 'refs/heads/main' && github.repository == 'nucypher/ferveo' with: cwd: ${{ matrix.component }} branchName: ${{ github.base_ref }} + features: "test-common" # The next steps have been adapted from https://raw.githubusercontent.com/unicode-org/icu4x/main/.github/workflows/build-test.yml diff --git a/ferveo/Cargo.toml b/ferveo/Cargo.toml index 6de79a05..8c52c087 100644 --- a/ferveo/Cargo.toml +++ b/ferveo/Cargo.toml @@ -44,6 +44,12 @@ digest = { version = "0.10.0", features = ["alloc"] } [package.metadata.cargo-udeps.ignore] development = ["pprof"] +[lib] +bench = false + +[features] +test-common = [] + [[example]] name = "pvdkg" path = "examples/pvdkg.rs" diff --git a/tpke/Cargo.toml b/tpke/Cargo.toml index ed7ff069..ad2f19d3 100644 --- a/tpke/Cargo.toml +++ b/tpke/Cargo.toml @@ -46,11 +46,10 @@ path = "benches/tpke.rs" harness = false required-features = ["test-common"] -# Disabling these benchmarks for now, as they are stable and we only ever run them locally. -#[[bench]] -#name = "arkworks" -#path = "benches/arkworks.rs" -#harness = false +[[bench]] +name = "arkworks" +path = "benches/arkworks.rs" +harness = false [profile.release] opt-level = 3 diff --git a/tpke/benches/arkworks.rs b/tpke/benches/arkworks.rs index 3abe9689..61d60cc1 100644 --- a/tpke/benches/arkworks.rs +++ b/tpke/benches/arkworks.rs @@ -9,7 +9,9 @@ use ark_bls12_381::{ use ark_ec::pairing::{prepare_g1, prepare_g2, Pairing}; use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::{BigInteger256, Field, One, UniformRand, Zero}; -use criterion::{black_box, criterion_group, BenchmarkId, Criterion}; +use criterion::{ + black_box, criterion_group, criterion_main, BenchmarkId, Criterion, +}; use group_threshold_cryptography::make_random_polynomial_at; use itertools::izip; use rand::prelude::StdRng; @@ -272,19 +274,25 @@ pub fn bench_random_poly(c: &mut Criterion) { } } +pub fn bench_dummy(_c: &mut Criterion) { + // Does nothing on purpose, but is required to make criterion happy. +} + criterion_group!( benches, - bench_mul, - bench_into_affine, - bench_into_projective, - bench_prepare_gx, - bench_pow, - bench_miller_loop, - bench_final_exponentiation, - bench_pairing, - bench_product_of_pairings, - bench_random_poly, + // Using this dummy benchmark to make criterion happy. + bench_dummy, + // Disabling these benchmarks for now, as they are stable and we only ever run them locally. + // bench_mul, + // bench_into_affine, + // bench_into_projective, + // bench_prepare_gx, + // bench_pow, + // bench_miller_loop, + // bench_final_exponentiation, + // bench_pairing, + // bench_product_of_pairings, + // bench_random_poly, ); -// Disabling these benchmarks for now, as they are stable and we only ever run them locally. -// criterion_main!(benches); +criterion_main!(benches); From a68d2d9b62414fd06afa234f240508d1c41e68a8 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Tue, 21 Feb 2023 13:09:52 +0100 Subject: [PATCH 32/36] sketch error handling in ferveo --- Cargo.lock | 2 +- Cargo.toml | 5 ++ ferveo-common/Cargo.toml | 4 -- ferveo-common/src/keypair.rs | 3 +- ferveo-common/src/lib.rs | 2 + ferveo-common/src/serialization.rs | 3 +- ferveo-common/src/utils.rs | 3 + ferveo-python/src/lib.rs | 4 +- ferveo/Cargo.toml | 7 +-- ferveo/examples/bench_primitives_size.rs | 10 ++-- ferveo/src/api.rs | 30 +++------- ferveo/src/dkg.rs | 11 ---- ferveo/src/dkg/common.rs | 11 ---- ferveo/src/dkg/pv.rs | 74 ++++++++++-------------- ferveo/src/lib.rs | 60 ++++++++++++------- ferveo/src/primitives.rs | 3 +- ferveo/src/vss.rs | 11 ---- ferveo/src/vss/pvss.rs | 57 ++++++++---------- rustfmt.toml | 3 +- subproductdomain/Cargo.toml | 4 -- subproductdomain/src/lib.rs | 18 +++--- tpke-python/src/lib.rs | 4 +- tpke-wasm/tests/node.rs | 3 +- tpke/Cargo.toml | 7 +-- tpke/benches/arkworks.rs | 6 +- tpke/benches/tpke.rs | 9 +-- tpke/src/ciphertext.rs | 19 +++--- tpke/src/combine.rs | 8 +-- tpke/src/context.rs | 3 +- tpke/src/decryption.rs | 6 +- tpke/src/hash_to_curve.rs | 15 ++--- tpke/src/key_share.rs | 3 +- tpke/src/lib.rs | 33 +++++------ tpke/src/refresh.rs | 6 +- 34 files changed, 185 insertions(+), 262 deletions(-) create mode 100644 ferveo-common/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index e0644cf3..2ab96e73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -831,6 +831,7 @@ dependencies = [ "serde_with", "subproductdomain", "subtle", + "thiserror", "zeroize", ] @@ -921,7 +922,6 @@ checksum = "221996f774192f0f718773def8201c4ae31f02616a54ccfc2d358bb0e5cefdec" name = "group-threshold-cryptography" version = "0.1.0" dependencies = [ - "anyhow", "ark-bls12-381", "ark-ec", "ark-ff", diff --git a/Cargo.toml b/Cargo.toml index 94d18e5a..8fef9444 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,8 @@ debug = true debug = true lto = true codegen-units = 1 + +# TODO: Enable before release +#[profile.release] +#opt-level = 3 +#lto = true \ No newline at end of file diff --git a/ferveo-common/Cargo.toml b/ferveo-common/Cargo.toml index 775c03b0..c9663f3a 100644 --- a/ferveo-common/Cargo.toml +++ b/ferveo-common/Cargo.toml @@ -12,7 +12,3 @@ serde = { version = "1.0", features = ["derive"] } ark-serialize = {version = "0.4", features = ["derive"]} serde_with = "2.2.0" bincode = "1.3.3" - -[profile.release] -opt-level = 3 -lto = true diff --git a/ferveo-common/src/keypair.rs b/ferveo-common/src/keypair.rs index 4f1eccec..cd972d37 100644 --- a/ferveo-common/src/keypair.rs +++ b/ferveo-common/src/keypair.rs @@ -1,7 +1,6 @@ use std::ops::Mul; -use ark_ec::pairing::Pairing; -use ark_ec::{AffineRepr, CurveGroup}; +use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; use ark_std::rand::RngCore; use serde::*; use serde_with::serde_as; diff --git a/ferveo-common/src/lib.rs b/ferveo-common/src/lib.rs index 61e7ef41..01e746a0 100644 --- a/ferveo-common/src/lib.rs +++ b/ferveo-common/src/lib.rs @@ -2,9 +2,11 @@ use ark_ec::pairing::Pairing; pub mod keypair; pub mod serialization; +pub mod utils; pub use keypair::*; pub use serialization::*; +pub use utils::*; #[derive(Clone, Debug, PartialEq)] /// Represents an external validator diff --git a/ferveo-common/src/serialization.rs b/ferveo-common/src/serialization.rs index 2107685f..32b5b984 100644 --- a/ferveo-common/src/serialization.rs +++ b/ferveo-common/src/serialization.rs @@ -3,8 +3,7 @@ //! Adapted from [o1-labs/proof-systems](https://raw.githubusercontent.com/o1-labs/proof-systems/31c76ceae3122f0ce09cded8260960ed5cbbe3d8/utils/src/serialization.rs). use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; -use serde; -use serde::{Deserialize, Serialize}; +use serde::{self, Deserialize, Serialize}; use serde_with::Bytes; // diff --git a/ferveo-common/src/utils.rs b/ferveo-common/src/utils.rs new file mode 100644 index 00000000..a7960bd1 --- /dev/null +++ b/ferveo-common/src/utils.rs @@ -0,0 +1,3 @@ +pub fn is_power_of_2(n: u32) -> bool { + n != 0 && (n & (n - 1)) == 0 +} diff --git a/ferveo-python/src/lib.rs b/ferveo-python/src/lib.rs index 1025cb63..35c1acdc 100644 --- a/ferveo-python/src/lib.rs +++ b/ferveo-python/src/lib.rs @@ -4,9 +4,7 @@ use std::fmt; use ferveo::api::E; use ferveo_common::serialization::{FromBytes, ToBytes}; -use pyo3::exceptions::PyValueError; -use pyo3::prelude::*; -use pyo3::types::PyBytes; +use pyo3::{exceptions::PyValueError, prelude::*, types::PyBytes}; use rand::thread_rng; fn from_py_bytes(bytes: &[u8]) -> PyResult { diff --git a/ferveo/Cargo.toml b/ferveo/Cargo.toml index 6de79a05..a6eac8f3 100644 --- a/ferveo/Cargo.toml +++ b/ferveo/Cargo.toml @@ -29,12 +29,13 @@ serde = { version = "1.0", features = ["derive"] } zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] } serde_bytes = { version = "0.11" } bincode = "1.3" -anyhow = "1.0" subtle = "2.4" itertools = "0.10.1" measure_time = "0.8" rand_core = "0.6.4" serde_with = "2.0.1" +thiserror = "1.0" +anyhow = "1.0" [dev-dependencies] criterion = "0.3" # supports pprof, # TODO: Figure out if/how we can update to 0.4 @@ -57,7 +58,3 @@ path = "examples/pvdkg.rs" name = "benchmarks" path = "benches/bench_main.rs" harness = false - -[profile.release] -opt-level = 3 -lto = true diff --git a/ferveo/examples/bench_primitives_size.rs b/ferveo/examples/bench_primitives_size.rs index ef8dc097..3bd95aea 100644 --- a/ferveo/examples/bench_primitives_size.rs +++ b/ferveo/examples/bench_primitives_size.rs @@ -1,7 +1,9 @@ -use std::collections::BTreeSet; -use std::fs::{create_dir_all, OpenOptions}; -use std::io::prelude::*; -use std::path::PathBuf; +use std::{ + collections::BTreeSet, + fs::{create_dir_all, OpenOptions}, + io::prelude::*, + path::PathBuf, +}; use ark_bls12_381::Bls12_381 as EllipticCurve; use ferveo::*; diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index a29996c4..13423bbd 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -1,18 +1,15 @@ use ark_poly::EvaluationDomain; -use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; -use ferveo_common::serialization::ser::serialize; pub use ferveo_common::{ExternalValidator, Keypair, PublicKey}; use group_threshold_cryptography as tpke; -use rand::rngs::StdRng; -use rand::{thread_rng, RngCore, SeedableRng}; +use rand::RngCore; use serde::{Deserialize, Serialize}; pub use tpke::api::{ decrypt_with_shared_secret, encrypt, share_combine_simple_precomputed, Ciphertext, DecryptionShareSimplePrecomputed as DecryptionShare, - DkgPublicKey, G1Prepared, Result, SharedSecret, UnblindingKey, E, + DkgPublicKey, G1Prepared, SharedSecret, UnblindingKey, E, }; -pub use crate::PubliclyVerifiableSS as Transcript; +pub use crate::{PubliclyVerifiableSS as Transcript, Result}; #[derive(Clone)] pub struct Dkg(crate::PubliclyVerifiableDkg); @@ -97,22 +94,11 @@ impl AggregatedTranscript { #[cfg(test)] mod test_ferveo_api { - use std::collections::HashMap; - use std::fmt::format; - - use ark_bls12_381::{Bls12_381 as E, G2Projective}; - use ark_ec::CurveGroup; - use ark_poly::EvaluationDomain; - use ark_serialize::CanonicalSerialize; - use ark_std::UniformRand; - use ferveo_common::PublicKey; - use group_threshold_cryptography as tpke; - use itertools::{iproduct, izip}; - use rand::prelude::StdRng; - use rand::SeedableRng; - - use crate::api::*; - use crate::dkg::test_common::*; + + use itertools::izip; + use rand::{prelude::StdRng, thread_rng, SeedableRng}; + + use crate::{api::*, dkg::test_common::*}; #[test] fn test_server_api_simple_tdec_precomputed() { diff --git a/ferveo/src/dkg.rs b/ferveo/src/dkg.rs index 32cdf933..7d5f507a 100644 --- a/ferveo/src/dkg.rs +++ b/ferveo/src/dkg.rs @@ -1,18 +1,7 @@ #![allow(clippy::many_single_char_names)] #![allow(non_snake_case)] -#![allow(unused_imports)] -use anyhow::anyhow; use ark_ec::pairing::Pairing; -use ark_ec::CurveGroup; -use ark_ff::Zero; -use ark_ff::{Field, One}; -use ark_poly::{ - polynomial::univariate::DensePolynomial, EvaluationDomain, Polynomial, -}; -use ark_serialize::*; -use bincode::Options; -use ed25519_dalek as ed25519; use serde::{Deserialize, Serialize}; pub mod common; diff --git a/ferveo/src/dkg/common.rs b/ferveo/src/dkg/common.rs index b4c1ec32..3df3691c 100644 --- a/ferveo/src/dkg/common.rs +++ b/ferveo/src/dkg/common.rs @@ -1,16 +1,5 @@ -use std::collections::HashMap; - -use anyhow::{anyhow, Result}; use ark_ec::pairing::Pairing; -use ark_ec::CurveGroup; -use ark_ff::{Field, One, PrimeField, Zero}; -use ark_poly::{polynomial::univariate::DensePolynomial, EvaluationDomain}; -use ark_std::{end_timer, start_timer}; use ferveo_common::ExternalValidator; -use ferveo_common::Rng; -use itertools::{izip, zip_eq}; -use measure_time::print_time; -use serde::{Deserialize, Serialize}; pub fn make_validators( validators: &[ExternalValidator], diff --git a/ferveo/src/dkg/pv.rs b/ferveo/src/dkg/pv.rs index ca7e41b0..c8d7eb77 100644 --- a/ferveo/src/dkg/pv.rs +++ b/ferveo/src/dkg/pv.rs @@ -1,27 +1,17 @@ use std::collections::BTreeMap; -use std::collections::HashMap; - -use anyhow::Context; -use anyhow::{anyhow, Result}; -use ark_ec::bn::TwistType::D; -use ark_ec::pairing::Pairing; -use ark_ec::{AffineRepr, CurveGroup, Group}; -use ark_ff::{Field, One, PrimeField, Zero}; -use ark_poly::{polynomial::univariate::DensePolynomial, EvaluationDomain}; -use ark_serialize::*; -use ark_std::{end_timer, start_timer}; -use ferveo_common::Rng; -use ferveo_common::{ExternalValidator, PublicKey}; -use group_threshold_cryptography as tpke; -use itertools::{izip, zip_eq}; + +use anyhow::{anyhow, Context}; +use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup, Group}; +use ark_poly::EvaluationDomain; +use ferveo_common::{is_power_of_2, ExternalValidator}; use measure_time::print_time; use rand::RngCore; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_with::serde_as; use crate::{ - aggregate, make_validators, AggregatedPvss, DkgState, Params, - PubliclyVerifiableParams, PubliclyVerifiableSS, Pvss, + aggregate, make_validators, AggregatedPvss, DkgState, Error, Params, + PubliclyVerifiableParams, PubliclyVerifiableSS, Pvss, Result, }; /// The DKG context that holds all of the local state for participating in the DKG @@ -54,11 +44,17 @@ impl PubliclyVerifiableDkg { me: &ExternalValidator, session_keypair: ferveo_common::Keypair, ) -> Result { - use ark_std::UniformRand; + // Make sure that the number of shares is a power of 2 for the FFT to work (Radix-2 FFT domain is being used) + if !is_power_of_2(params.shares_num) { + return Err(Error::Other(anyhow!( + "number of shares must be a power of 2" + ))); + } + let domain = ark_poly::Radix2EvaluationDomain::::new( params.shares_num as usize, ) - .ok_or_else(|| anyhow!("unable to construct domain"))?; + .expect("unable to construct domain"); // keep track of the owner of this instance in the validator set let me = validators.iter().position(|probe| me == probe).context( @@ -89,16 +85,15 @@ impl PubliclyVerifiableDkg { /// `rng` is a cryptographic random number generator /// Returns a PVSS dealing message to post on-chain pub fn share(&mut self, rng: &mut R) -> Result> { - use ark_std::UniformRand; print_time!("PVSS Sharing"); let vss = self.create_share(rng)?; match self.state { DkgState::Sharing { .. } | DkgState::Dealt => { Ok(Message::Deal(vss)) } - _ => { - Err(anyhow!("DKG is not in a valid state to deal PVSS shares")) - } + _ => Err(Error::Other(anyhow!( + "DKG is not in a valid state to deal PVSS shares" + ))), } } @@ -120,9 +115,9 @@ impl PubliclyVerifiableDkg { final_key, })) } - _ => Err(anyhow!( + _ => Err(Error::Other(anyhow!( "Not enough PVSS transcripts received to aggregate" - )), + ))), } } @@ -154,9 +149,9 @@ impl PubliclyVerifiableDkg { .position(|probe| sender == &probe.validator) .context("dkg received unknown dealer")?; if self.vss.contains_key(&(sender as u32)) { - Err(anyhow!("Repeat dealer {}", sender)) + Err(Error::Other(anyhow!("Repeat dealer {}", sender))) } else if !pvss.verify_optimistic() { - Err(anyhow!("Invalid PVSS transcript")) + Err(Error::Other(anyhow!("Invalid PVSS transcript"))) } else { Ok(()) } @@ -166,20 +161,20 @@ impl PubliclyVerifiableDkg { let verified_shares = vss.verify_aggregation(self)?; // we reject aggregations that fail to meet the security threshold if verified_shares < minimum_shares { - Err(anyhow!( + Err(Error::Other(anyhow!( "Aggregation failed because the verified shares was insufficient" - )) + ))) } else if &self.final_key() == final_key { Ok(()) } else { - Err(anyhow!( + Err(Error::Other(anyhow!( "The final key was not correctly derived from the aggregated transcripts" - )) + ))) } } - _ => Err(anyhow!( + _ => Err(Error::Other(anyhow!( "DKG state machine is not in correct state to verify this message" - )), + ))), } } @@ -222,9 +217,9 @@ impl PubliclyVerifiableDkg { }; Ok(()) } - _ => Err(anyhow!( + _ => Err(Error::Other(anyhow!( "DKG state machine is not in correct state to apply this message" - )), + ))), } } @@ -348,10 +343,6 @@ pub(crate) mod test_common { security_threshold: u32, shares_num: u32, ) -> PubliclyVerifiableDkg { - // Make sure that the number of shares is a power of 2 for the FFT to work (Radix-2 FFT domain is being used) - let is_power_of_2 = |n: u32| n != 0 && (n & (n - 1)) == 0; - assert!(is_power_of_2(shares_num)); - let rng = &mut ark_std::test_rng(); // Gather everyone's transcripts @@ -401,10 +392,7 @@ mod test_dkg_init { keypair, ) .expect_err("Test failed"); - assert_eq!( - err.to_string(), - "could not find this validator in the provided validator set" - ) + assert_eq!(err.to_string(), "Something went wrong") } } diff --git a/ferveo/src/lib.rs b/ferveo/src/lib.rs index f903392b..c32fe31d 100644 --- a/ferveo/src/lib.rs +++ b/ferveo/src/lib.rs @@ -1,44 +1,60 @@ -#![allow(unused_imports)] - pub mod api; pub mod dkg; pub mod primitives; mod vss; // TODO: Replace with concrete error type -pub use anyhow::Error; pub use dkg::*; +use group_threshold_cryptography as tpke; pub use primitives::*; pub use vss::*; +#[derive(Debug, thiserror::Error)] +pub enum Error { + /// Threshold encryption error + #[error("Threshold encryption error")] + ThresholdEncryptionError(#[from] tpke::Error), + + // /// Not all validator session keys have been announced + // #[error("Not enough validators (expected {0}, got {1})")] + // InvalidValidatorCount(usize, usize), + // + // /// Aggregation does not match received PVSS instances + // #[error("Aggregation does not match received PVSS instances")] + // InvalidAggregation, + // + // /// Number of shares parameter must be a power of two + // #[error("Number of shares parameter must be a power of two. Got {0}")] + // InvalidShareNumberParameter(usize), + // + // /// DKG is not in a valid state to deal PVSS shares + // #[error("Invalid DKG state")] + // InvalidDkgState(), + // + // /// Not enough PVSS transcripts received to aggregate + // #[error("Not enough PVSS transcripts received to aggregate (expected {0}, got {1})")] + // NotEnoughPVSSTranscripts(usize, usize), + #[error("Something went wrong")] + Other(#[from] anyhow::Error), +} + +pub type Result = std::result::Result; + #[cfg(test)] mod test_dkg_full { use std::collections::HashMap; - use anyhow::{anyhow, Result}; - use ark_bls12_381::{ - Bls12_381 as E, Bls12_381, Fr, G1Affine, G2Projective, - }; - use ark_ec::bls12::G2Affine; - use ark_ec::pairing::Pairing; - use ark_ec::{AffineRepr, CurveGroup}; - use ark_ff::{Field, One, PrimeField, Zero}; - use ark_ff::{Fp12, UniformRand}; - use ark_poly::{polynomial::univariate::DensePolynomial, EvaluationDomain}; + use ark_bls12_381::{Bls12_381 as E, Fr, G1Affine}; + use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; + use ark_ff::{UniformRand, Zero}; + use ark_poly::EvaluationDomain; use ark_std::test_rng; - use ark_std::{end_timer, start_timer}; - use ferveo_common::Rng; - use ferveo_common::{ExternalValidator, Keypair}; + use ferveo_common::Keypair; use group_threshold_cryptography as tpke; use group_threshold_cryptography::{ Ciphertext, DecryptionShareSimple, DecryptionShareSimplePrecomputed, }; - use itertools::Itertools; - use itertools::{izip, zip_eq}; - use measure_time::print_time; - use rand::prelude::StdRng; - use rand::SeedableRng; - use serde::{Deserialize, Serialize}; + use itertools::{izip, Itertools}; use super::*; use crate::dkg::pv::test_common::*; diff --git a/ferveo/src/primitives.rs b/ferveo/src/primitives.rs index a87d142c..717b0430 100644 --- a/ferveo/src/primitives.rs +++ b/ferveo/src/primitives.rs @@ -1,5 +1,4 @@ -use ark_ec::pairing::Pairing; -use ark_ec::AffineRepr; +use ark_ec::{pairing::Pairing, AffineRepr}; // pub fn batch_to_projective( // p: &[A], diff --git a/ferveo/src/vss.rs b/ferveo/src/vss.rs index 2d65d650..b90949c8 100644 --- a/ferveo/src/vss.rs +++ b/ferveo/src/vss.rs @@ -1,17 +1,6 @@ pub mod pvss; -use std::collections::HashMap; - -use anyhow::{anyhow, Result}; -use ark_ec::CurveGroup; -use ark_ff::{Field, One, PrimeField, Zero}; -use ark_poly::{polynomial::univariate::DensePolynomial, EvaluationDomain}; -use ark_std::{end_timer, start_timer}; -use ferveo_common::Rng; -use itertools::{izip, zip_eq}; -use measure_time::print_time; pub use pvss::*; -use serde::{Deserialize, Serialize}; // TODO: Figure out if you need to / can use this struct // /// The possible States of a VSS instance diff --git a/ferveo/src/vss/pvss.rs b/ferveo/src/vss/pvss.rs index f06883a5..d79e72f9 100644 --- a/ferveo/src/vss/pvss.rs +++ b/ferveo/src/vss/pvss.rs @@ -1,36 +1,29 @@ -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::marker::PhantomData; -use std::ops::{Add, Mul}; - -use anyhow::{anyhow, Result}; -use ark_ec::bn::G2Affine; -use ark_ec::pairing::Pairing; -use ark_ec::{AffineRepr, CurveGroup}; -use ark_ff::UniformRand; -use ark_ff::{Field, One, PrimeField, Zero}; -use ark_poly::DenseUVPolynomial; -use ark_poly::{polynomial::univariate::DensePolynomial, EvaluationDomain}; -use ark_serialize::*; -use ark_std::{end_timer, start_timer}; -use ferveo_common::Rng; -use ferveo_common::{Keypair, PublicKey}; +use std::{marker::PhantomData, ops::Mul}; + +use anyhow::anyhow; +use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; +use ark_ff::{Field, Zero}; +use ark_poly::{ + polynomial::univariate::DensePolynomial, DenseUVPolynomial, + EvaluationDomain, +}; use group_threshold_cryptography as tpke; -use itertools::izip; -use itertools::{zip_eq, Itertools}; +use itertools::Itertools; use measure_time::print_time; use rand::RngCore; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use serde_with::serde_as; use subproductdomain::fast_multiexp; use tpke::{ prepare_combine_simple, refresh_private_key_share, - update_share_for_recovery, Ciphertext, DecryptionShareFast, - DecryptionShareSimple, DecryptionShareSimplePrecomputed, PrivateKeyShare, + update_share_for_recovery, Ciphertext, DecryptionShareSimple, + DecryptionShareSimplePrecomputed, PrivateKeyShare, }; -use crate::PubliclyVerifiableDkg; -use crate::{batch_to_projective_g1, batch_to_projective_g2}; +use crate::{ + batch_to_projective_g1, batch_to_projective_g2, Error, + PubliclyVerifiableDkg, Result, +}; /// These are the blinded evaluations of shares of a single random polynomial pub type ShareEncryptions = ::G2Affine; @@ -126,9 +119,9 @@ impl PubliclyVerifiableSS { }) .collect::>>(); if shares.len() != dkg.validators.len() { - return Err(anyhow!( + return Err(Error::Other(anyhow!( "Not all validator session keys have been announced" - )); + ))); } // phi.zeroize(); // TODO zeroize? // TODO: Cross check proof of knowledge check with the whitepaper; this check proves that there is a relationship between the secret and the pvss transcript @@ -215,9 +208,9 @@ impl PubliclyVerifiableSS { if y.into_affine() == self.coeffs[0] { Ok(shares_total) } else { - Err(anyhow!( + Err(Error::Other(anyhow!( "aggregation does not match received PVSS instances" - )) + ))) } } @@ -260,8 +253,8 @@ impl PubliclyVerifiableSS { aad, g_inv, ) + .map_err(|e| e.into()) } - pub fn make_decryption_share_simple_precomputed( &self, ciphertext: &Ciphertext, @@ -287,6 +280,7 @@ impl PubliclyVerifiableSS { &lagrange_coeffs[validator_index], g_inv, ) + .map_err(|e| e.into()) } pub fn refresh_decryption_share( @@ -318,6 +312,7 @@ impl PubliclyVerifiableSS { aad, &dkg.pvss_params.g_inv(), ) + .map_err(|e| e.into()) } pub fn update_private_key_share_for_recovery( @@ -408,7 +403,6 @@ mod test_pvss { use ark_bls12_381::Bls12_381 as EllipticCurve; use ark_ec::AffineRepr; use ark_ff::UniformRand; - use ferveo_common::ExternalValidator; use super::*; use crate::dkg::pv::test_common::*; @@ -509,7 +503,6 @@ mod test_pvss { /// incorrect constant term, the verification fails #[test] fn test_verify_aggregation_fails_if_constant_term_wrong() { - use std::ops::Neg; let dkg = setup_dealt_dkg(); let mut aggregated = aggregate(&dkg); while aggregated.coeffs[0] == G1::zero() { @@ -522,7 +515,7 @@ mod test_pvss { .verify_aggregation(&dkg) .expect_err("Test failed") .to_string(), - "aggregation does not match received PVSS instances" + "Something went wrong" ) } } diff --git a/rustfmt.toml b/rustfmt.toml index 8ad17fc5..0a61d11a 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -13,4 +13,5 @@ use_try_shorthand = false use_field_init_shorthand = false force_explicit_abi = true unstable_features = true -group_imports = "StdExternalCrate" \ No newline at end of file +group_imports = "StdExternalCrate" +imports_granularity = "Crate" \ No newline at end of file diff --git a/subproductdomain/Cargo.toml b/subproductdomain/Cargo.toml index 6de84da8..149ea954 100644 --- a/subproductdomain/Cargo.toml +++ b/subproductdomain/Cargo.toml @@ -15,7 +15,3 @@ ark-poly = "0.4" [dev-dependencies] ark-bls12-381 = "0.4" - -[profile.release] -opt-level = 3 -lto = true \ No newline at end of file diff --git a/subproductdomain/src/lib.rs b/subproductdomain/src/lib.rs index 723b4ed7..63dd11cf 100644 --- a/subproductdomain/src/lib.rs +++ b/subproductdomain/src/lib.rs @@ -3,15 +3,14 @@ use std::mem; -use ark_ec::pairing::Pairing; -use ark_ec::scalar_mul::fixed_base::FixedBase; -use ark_ec::AffineRepr; -use ark_ec::CurveGroup; +use ark_ec::{ + pairing::Pairing, scalar_mul::fixed_base::FixedBase, AffineRepr, CurveGroup, +}; use ark_ff::{FftField, Field, Zero}; -use ark_poly::univariate::DensePolynomial; -use ark_poly::DenseUVPolynomial; -use ark_poly::EvaluationDomain; -use ark_poly::{Polynomial, Radix2EvaluationDomain}; +use ark_poly::{ + univariate::DensePolynomial, DenseUVPolynomial, EvaluationDomain, + Polynomial, Radix2EvaluationDomain, +}; /// Compute a fast multiexp of many scalars times the same base /// Only convenient for when called once with given base; if called @@ -386,8 +385,7 @@ pub fn toeplitz_mul( mod tests { use ark_ec::pairing::Pairing; use ark_ff::{One, Zero}; - use ark_poly::polynomial::univariate::DensePolynomial; - use ark_poly::Polynomial; + use ark_poly::{polynomial::univariate::DensePolynomial, Polynomial}; use ark_std::UniformRand; use super::*; diff --git a/tpke-python/src/lib.rs b/tpke-python/src/lib.rs index b3e20c6f..08e635a6 100644 --- a/tpke-python/src/lib.rs +++ b/tpke-python/src/lib.rs @@ -3,9 +3,7 @@ extern crate alloc; extern crate group_threshold_cryptography as tpke; use ferveo_common::serialization::ToBytes; -use pyo3::exceptions::PyValueError; -use pyo3::prelude::*; -use pyo3::types::PyBytes; +use pyo3::{exceptions::PyValueError, prelude::*, types::PyBytes}; #[pyclass(module = "tpke")] pub struct DecryptionShare(tpke::api::DecryptionShareSimplePrecomputed); diff --git a/tpke-wasm/tests/node.rs b/tpke-wasm/tests/node.rs index 1ec52aee..b454fa04 100644 --- a/tpke-wasm/tests/node.rs +++ b/tpke-wasm/tests/node.rs @@ -3,8 +3,7 @@ extern crate group_threshold_cryptography as tpke; extern crate wasm_bindgen_test; -use tpke_wasm::test_common::*; -use tpke_wasm::*; +use tpke_wasm::{test_common::*, *}; use wasm_bindgen_test::*; #[test] diff --git a/tpke/Cargo.toml b/tpke/Cargo.toml index ed7ff069..ca812882 100644 --- a/tpke/Cargo.toml +++ b/tpke/Cargo.toml @@ -19,8 +19,7 @@ subproductdomain = { path = "../subproductdomain" } ferveo-common = { path = "../ferveo-common" } rand_core = "0.6" rand = "0.8" -thiserror = "=1.0.30" -anyhow = "=1.0" +thiserror = "1.0" miracl_core = "=2.3.0" ark-ff = "0.4" ark-ec = "0.4" @@ -51,7 +50,3 @@ required-features = ["test-common"] #name = "arkworks" #path = "benches/arkworks.rs" #harness = false - -[profile.release] -opt-level = 3 -lto = true diff --git a/tpke/benches/arkworks.rs b/tpke/benches/arkworks.rs index 3abe9689..a15300e0 100644 --- a/tpke/benches/arkworks.rs +++ b/tpke/benches/arkworks.rs @@ -6,8 +6,10 @@ use std::ops::Mul; use ark_bls12_381::{ Bls12_381, Fr, G1Affine, G1Projective, G2Affine, G2Projective, }; -use ark_ec::pairing::{prepare_g1, prepare_g2, Pairing}; -use ark_ec::{AffineRepr, CurveGroup}; +use ark_ec::{ + pairing::{prepare_g1, prepare_g2, Pairing}, + AffineRepr, CurveGroup, +}; use ark_ff::{BigInteger256, Field, One, UniformRand, Zero}; use criterion::{black_box, criterion_group, BenchmarkId, Criterion}; use group_threshold_cryptography::make_random_polynomial_at; diff --git a/tpke/benches/tpke.rs b/tpke/benches/tpke.rs index d3373726..f06df1e8 100644 --- a/tpke/benches/tpke.rs +++ b/tpke/benches/tpke.rs @@ -3,14 +3,15 @@ use std::collections::HashMap; use ark_bls12_381::{Bls12_381, Fr, G1Affine as G1, G2Affine as G2}; -use ark_ec::pairing::Pairing; -use ark_ec::AffineRepr; +use ark_ec::{pairing::Pairing, AffineRepr}; use ark_ff::Zero; use criterion::{ black_box, criterion_group, criterion_main, BenchmarkId, Criterion, }; -use group_threshold_cryptography::test_common::{setup_fast, setup_simple}; -use group_threshold_cryptography::*; +use group_threshold_cryptography::{ + test_common::{setup_fast, setup_simple}, + *, +}; use rand::prelude::StdRng; use rand_core::{RngCore, SeedableRng}; diff --git a/tpke/src/ciphertext.rs b/tpke/src/ciphertext.rs index dff76319..db43efb0 100644 --- a/tpke/src/ciphertext.rs +++ b/tpke/src/ciphertext.rs @@ -1,7 +1,6 @@ use std::ops::Mul; -use ark_ec::pairing::Pairing; -use ark_ec::AffineRepr; +use ark_ec::{pairing::Pairing, AffineRepr}; use ark_ff::{One, UniformRand}; use ark_serialize::{CanonicalSerialize, Compress}; use chacha20poly1305::{ @@ -13,7 +12,7 @@ use serde::{Deserialize, Serialize}; use serde_with::serde_as; use sha2::{digest::Digest, Sha256}; -use crate::{htp_bls12381_g2, Result, ThresholdEncryptionError}; +use crate::{htp_bls12381_g2, Error, Result}; #[serde_as] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -76,7 +75,7 @@ pub fn encrypt( let nonce = nonce_from_commitment::(commitment)?; let ciphertext = shared_secret_to_chacha::(&product)? .encrypt(&nonce, message) - .map_err(ThresholdEncryptionError::SymmetricEncryptionError)? + .map_err(Error::SymmetricEncryptionError)? .to_vec(); // w let auth_tag = construct_tag_hash::(commitment, &ciphertext, aad)? @@ -116,7 +115,7 @@ pub fn check_ciphertext_validity( if is_ciphertext_valid { Ok(()) } else { - Err(ThresholdEncryptionError::CiphertextVerificationFailed.into()) + Err(Error::CiphertextVerificationFailed) } } @@ -144,7 +143,7 @@ fn decrypt_with_shared_secret_unchecked( let plaintext = shared_secret_to_chacha::(shared_secret)? .decrypt(&nonce, ciphertext.as_ref()) - .map_err(|_| ThresholdEncryptionError::CiphertextVerificationFailed)? + .map_err(|_| Error::CiphertextVerificationFailed)? .to_vec(); Ok(plaintext) @@ -190,9 +189,8 @@ fn hash_to_g2( let point = htp_bls12381_g2(message); let mut point_ser: Vec = Vec::new(); point.serialize_uncompressed(&mut point_ser)?; - T::deserialize_uncompressed(&point_ser[..]).map_err(|err| { - ThresholdEncryptionError::ArkworksSerializationError(err).into() - }) + T::deserialize_uncompressed(&point_ser[..]) + .map_err(Error::ArkworksSerializationError) } fn construct_tag_hash( @@ -212,8 +210,7 @@ mod tests { use ark_std::test_rng; - use crate::test_common::*; - use crate::*; + use crate::{test_common::*, *}; type E = ark_bls12_381::Bls12_381; diff --git a/tpke/src/combine.rs b/tpke/src/combine.rs index ec094d97..b7e3c3d5 100644 --- a/tpke/src/combine.rs +++ b/tpke/src/combine.rs @@ -9,8 +9,8 @@ use subproductdomain::SubproductDomain; use crate::{ verify_decryption_shares_fast, Ciphertext, DecryptionShareFast, - DecryptionShareSimple, DecryptionShareSimplePrecomputed, - PublicDecryptionContextFast, Result, ThresholdEncryptionError, + DecryptionShareSimple, DecryptionShareSimplePrecomputed, Error, + PublicDecryptionContextFast, Result, }; pub fn prepare_combine_fast( @@ -106,9 +106,7 @@ pub fn share_combine_fast( decryption_shares, ); if !is_valid_shares { - return Err( - ThresholdEncryptionError::DecryptionShareVerificationFailed.into(), - ); + return Err(Error::DecryptionShareVerificationFailed); } Ok(share_combine_fast_unchecked( decryption_shares, diff --git a/tpke/src/context.rs b/tpke/src/context.rs index 5ba408b6..552e3743 100644 --- a/tpke/src/context.rs +++ b/tpke/src/context.rs @@ -1,7 +1,6 @@ use std::ops::Mul; -use ark_ec::pairing::Pairing; -use ark_ec::CurveGroup; +use ark_ec::{pairing::Pairing, CurveGroup}; use crate::{ check_ciphertext_validity, prepare_combine_simple, BlindedKeyShare, diff --git a/tpke/src/decryption.rs b/tpke/src/decryption.rs index ff1a7a26..ee8bdf23 100644 --- a/tpke/src/decryption.rs +++ b/tpke/src/decryption.rs @@ -1,8 +1,6 @@ use std::ops::Mul; -use anyhow::Result; -use ark_ec::pairing::Pairing; -use ark_ec::CurveGroup; +use ark_ec::{pairing::Pairing, CurveGroup}; use ark_ff::{Field, One, Zero}; use ferveo_common::serialization; use itertools::{izip, zip_eq}; @@ -12,7 +10,7 @@ use serde_with::serde_as; use crate::{ check_ciphertext_validity, generate_random, Ciphertext, PrivateKeyShare, - PublicDecryptionContextFast, PublicDecryptionContextSimple, + PublicDecryptionContextFast, PublicDecryptionContextSimple, Result, }; #[serde_as] diff --git a/tpke/src/hash_to_curve.rs b/tpke/src/hash_to_curve.rs index 55b75f21..dc925170 100644 --- a/tpke/src/hash_to_curve.rs +++ b/tpke/src/hash_to_curve.rs @@ -4,16 +4,11 @@ #![allow(dead_code)] use ark_bls12_381::g2::Config; -use ark_ec::short_weierstrass::Affine; -use ark_ec::AffineRepr; -use miracl_core::bls12381::big::BIG; -use miracl_core::bls12381::dbig::DBIG; -use miracl_core::bls12381::ecp; -use miracl_core::bls12381::ecp2::ECP2; -use miracl_core::bls12381::fp::FP; -use miracl_core::bls12381::fp2::FP2; -use miracl_core::bls12381::rom; -use miracl_core::hmac; +use ark_ec::{short_weierstrass::Affine, AffineRepr}; +use miracl_core::{ + bls12381::{big::BIG, dbig::DBIG, ecp, ecp2::ECP2, fp::FP, fp2::FP2, rom}, + hmac, +}; fn ceil(a: usize, b: usize) -> usize { (a - 1) / b + 1 diff --git a/tpke/src/key_share.rs b/tpke/src/key_share.rs index e0289689..884c7fca 100644 --- a/tpke/src/key_share.rs +++ b/tpke/src/key_share.rs @@ -1,7 +1,6 @@ use std::ops::Mul; -use ark_ec::pairing::Pairing; -use ark_ec::{AffineRepr, CurveGroup}; +use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; use ark_ff::One; use ark_std::UniformRand; use rand_core::RngCore; diff --git a/tpke/src/lib.rs b/tpke/src/lib.rs index 62a54b25..84134c0d 100644 --- a/tpke/src/lib.rs +++ b/tpke/src/lib.rs @@ -27,7 +27,7 @@ pub use refresh::*; pub mod api; #[derive(Debug, thiserror::Error)] -pub enum ThresholdEncryptionError { +pub enum Error { /// Ciphertext verification failed /// Refers to the check 4.4.2 in the paper: https://eprint.iacr.org/2022/898.pdf #[error("Ciphertext verification failed")] @@ -63,21 +63,21 @@ pub enum ThresholdEncryptionError { ArkworksSerializationError(#[from] ark_serialize::SerializationError), } -pub type Result = anyhow::Result; +pub type Result = std::result::Result; /// Factory functions for testing #[cfg(any(test, feature = "test-common"))] pub mod test_common { - use std::ops::Mul; - use std::usize; + use std::{ops::Mul, usize}; pub use ark_bls12_381::Bls12_381 as EllipticCurve; use ark_ec::{pairing::Pairing, AffineRepr}; pub use ark_ff::UniformRand; use ark_ff::{Field, One, Zero}; - use ark_poly::univariate::DensePolynomial; - use ark_poly::DenseUVPolynomial; - use ark_poly::{EvaluationDomain, Polynomial}; + use ark_poly::{ + univariate::DensePolynomial, DenseUVPolynomial, EvaluationDomain, + Polynomial, + }; use itertools::izip; use rand_core::RngCore; use subproductdomain::fast_multiexp; @@ -274,24 +274,23 @@ pub mod test_common { #[cfg(test)] mod tests { - use std::collections::HashMap; - use std::ops::Mul; + use std::{collections::HashMap, ops::Mul}; use ark_bls12_381::Fr; - use ark_ec::pairing::Pairing; - use ark_ec::{AffineRepr, CurveGroup}; + use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; use ark_ff::Zero; use ark_std::{test_rng, UniformRand}; use ferveo_common::{FromBytes, ToBytes}; use rand_core::RngCore; - use crate::refresh::{ - make_random_polynomial_at, prepare_share_updates_for_recovery, - recover_share_from_updated_private_shares, refresh_private_key_share, - update_share_for_recovery, + use crate::{ + refresh::{ + make_random_polynomial_at, prepare_share_updates_for_recovery, + recover_share_from_updated_private_shares, + refresh_private_key_share, update_share_for_recovery, + }, + test_common::{setup_simple, *}, }; - use crate::test_common::setup_simple; - use crate::test_common::*; type E = ark_bls12_381::Bls12_381; type TargetField = ::TargetField; diff --git a/tpke/src/refresh.rs b/tpke/src/refresh.rs index 2ef6e6c2..d7ebfa87 100644 --- a/tpke/src/refresh.rs +++ b/tpke/src/refresh.rs @@ -1,8 +1,6 @@ -use std::ops::Mul; -use std::usize; +use std::{ops::Mul, usize}; -use ark_ec::pairing::Pairing; -use ark_ec::{AffineRepr, CurveGroup}; +use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; use ark_ff::Zero; use ark_poly::{univariate::DensePolynomial, DenseUVPolynomial, Polynomial}; use itertools::zip_eq; From b38b336981f43d6fcf2ebe9c32d8a3c253b14b51 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Tue, 21 Feb 2023 15:17:08 +0100 Subject: [PATCH 33/36] add browser example for tpke-wasm --- Cargo.lock | 6 +- tpke-wasm/Cargo.toml | 4 +- tpke-wasm/examples/browser/.gitignore | 10 + tpke-wasm/examples/browser/README.md | 17 + tpke-wasm/examples/browser/bootstrap.js | 5 + tpke-wasm/examples/browser/index.html | 12 + tpke-wasm/examples/browser/index.js | 84 + tpke-wasm/examples/browser/package.json | 25 + tpke-wasm/examples/browser/webpack.config.js | 12 + tpke-wasm/examples/browser/yarn.lock | 3826 ++++++++++++++++++ tpke-wasm/examples/node/README.md | 7 + tpke-wasm/pkg/.gitkeep | 0 12 files changed, 4004 insertions(+), 4 deletions(-) create mode 100644 tpke-wasm/examples/browser/.gitignore create mode 100644 tpke-wasm/examples/browser/README.md create mode 100644 tpke-wasm/examples/browser/bootstrap.js create mode 100644 tpke-wasm/examples/browser/index.html create mode 100644 tpke-wasm/examples/browser/index.js create mode 100644 tpke-wasm/examples/browser/package.json create mode 100644 tpke-wasm/examples/browser/webpack.config.js create mode 100644 tpke-wasm/examples/browser/yarn.lock delete mode 100644 tpke-wasm/pkg/.gitkeep diff --git a/Cargo.lock b/Cargo.lock index e0644cf3..89b7037f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -848,14 +848,14 @@ dependencies = [ [[package]] name = "ferveo-python" -version = "0.1.0" +version = "0.1.1" dependencies = [ "derive_more", "ferveo", "ferveo-common", "group-threshold-cryptography", "pyo3", - "pyo3-build-config 0.18.1", + "pyo3-build-config 0.17.3", "rand 0.8.5", ] @@ -2050,7 +2050,7 @@ dependencies = [ [[package]] name = "tpke-wasm" -version = "0.1.0" +version = "0.1.0-alpha.1" dependencies = [ "ark-bls12-381", "ark-ec", diff --git a/tpke-wasm/Cargo.toml b/tpke-wasm/Cargo.toml index 0ae2b59f..c24c898e 100644 --- a/tpke-wasm/Cargo.toml +++ b/tpke-wasm/Cargo.toml @@ -1,11 +1,13 @@ [package] name = "tpke-wasm" -version = "0.1.0" +version = "0.1.0-alpha.1" authors = ["Piotr Roslaniec "] edition = "2021" license = "GPL-3.0-only" readme = "README.md" categories = ["cryptography", "no-std"] +repository = "https://github.com/nucypher/ferveo" +description = "WASM bindings for group-threshold-cryptography crate" [lib] crate-type = ["cdylib", "rlib"] diff --git a/tpke-wasm/examples/browser/.gitignore b/tpke-wasm/examples/browser/.gitignore new file mode 100644 index 00000000..a37ab157 --- /dev/null +++ b/tpke-wasm/examples/browser/.gitignore @@ -0,0 +1,10 @@ +/node_modules/ +/build/ +/lib/ +/dist/ +/docs/ +.idea/* + +.DS_Store +coverage +*.log diff --git a/tpke-wasm/examples/browser/README.md b/tpke-wasm/examples/browser/README.md new file mode 100644 index 00000000..2984a7fd --- /dev/null +++ b/tpke-wasm/examples/browser/README.md @@ -0,0 +1,17 @@ +# `tpke-wasm` in the browser: + +## Usage + +Make sure `pkg` is build with correct target: +```bash +cd ../../ +wasm-pack build --target web +``` + +Install dependencies and run tests: +```bash +$ yarn install +$ yarn start +``` + +Visit http://localhost:8080/ in your browser. diff --git a/tpke-wasm/examples/browser/bootstrap.js b/tpke-wasm/examples/browser/bootstrap.js new file mode 100644 index 00000000..7934d627 --- /dev/null +++ b/tpke-wasm/examples/browser/bootstrap.js @@ -0,0 +1,5 @@ +// A dependency graph that contains any wasm must all be imported +// asynchronously. This `bootstrap.js` file does the single async import, so +// that no one else needs to worry about it again. +import("./index.js") + .catch(e => console.error("Error importing `index.js`:", e)); diff --git a/tpke-wasm/examples/browser/index.html b/tpke-wasm/examples/browser/index.html new file mode 100644 index 00000000..f36204aa --- /dev/null +++ b/tpke-wasm/examples/browser/index.html @@ -0,0 +1,12 @@ + + + + + tpke-wasm example + + + + +

Check console for results

+ + diff --git a/tpke-wasm/examples/browser/index.js b/tpke-wasm/examples/browser/index.js new file mode 100644 index 00000000..e15cd3d9 --- /dev/null +++ b/tpke-wasm/examples/browser/index.js @@ -0,0 +1,84 @@ +import { + Ciphertext, + decryptWithSharedSecret, + Dkg, + encrypt, + SharedSecretSimpleBuilder, + DecryptionShareSimple, +} from "tpke-wasm"; + +const zip = (a, b) => a.map((k, i) => [k, b[i]]); + +const areEqual = (first, second) => + first.length === second.length && first.every((value, index) => value === second[index]); + +const sharesNum = 16; +const threshold = (sharesNum * 2) / 3; +const msg = new TextEncoder().encode("my-msg"); +const aad = new TextEncoder().encode("my-aad"); + +const dkg = new Dkg(threshold, sharesNum); + +// +// On the client side +// + +// Encrypt the message +const ciphertext = encrypt(msg, aad, dkg.public_key); + +// Serialize and send to validators +const ciphertext_bytes = ciphertext.toBytes(); + +// +// On the server side +// + +const ciphertext2 = Ciphertext.fromBytes(ciphertext_bytes); +console.assert(areEqual(ciphertext.toBytes(), ciphertext2.toBytes())); + +// Create decryption shares + +const decryptionShares = []; +for (let i = 0; i < threshold; i++) { + const share = dkg.makeDecryptionShareSimple(ciphertext, aad, i); + decryptionShares.push(share); +} + +const domainPoints = []; +for (let i = 0; i < threshold; i++) { + const point = dkg.getDomainPoint(i); + domainPoints.push(point); +} + +// Serialize and send back to client +const decryptionSharesBytes = decryptionShares.map((s) => s.toBytes()); + +// +// On the client side +// + +const decryptionShares2 = decryptionSharesBytes.map((b) => + DecryptionShareSimple.fromBytes(b) +); +zip(decryptionShares, decryptionShares2).map(([s1, s2]) => + console.assert(areEqual(s1.toBytes(), s2.toBytes())) +) + +// Combine shares into a shared secret +const ssBuilder = new SharedSecretSimpleBuilder(threshold); +decryptionShares.forEach((share) => ssBuilder.addDecryptionShare(share)); + +domainPoints.forEach((point) => ssBuilder.addDomainPoint(point)); + +const shared_secret = ssBuilder.build(); + +// Decrypt the message +const plaintext = decryptWithSharedSecret( + ciphertext, + aad, + shared_secret, + dkg.gInv +); +console.assert(areEqual(plaintext, msg)); + +console.log("Success! 🎉") \ No newline at end of file diff --git a/tpke-wasm/examples/browser/package.json b/tpke-wasm/examples/browser/package.json new file mode 100644 index 00000000..1ef7db87 --- /dev/null +++ b/tpke-wasm/examples/browser/package.json @@ -0,0 +1,25 @@ +{ + "name": "tpke-wasm-example-bundler", + "version": "0.1.0", + "description": "A usage example for tpke-wasm", + "main": "index.js", + "private": true, + "author": "Piotr Rosłaniec ", + "scripts": { + "build": "webpack --config webpack.config.js", + "start": "webpack-dev-server" + }, + "license": "GPL-3.0-only", + "dependencies": { + "tpke-wasm": "../../pkg" + }, + "devDependencies": { + "copy-webpack-plugin": "^5.0.0", + "webpack": "^4.29.3", + "webpack-cli": "^3.1.0", + "webpack-dev-server": "^3.1.5" + }, + "resolutions": { + "glob-parent": "5.1.2" + } +} \ No newline at end of file diff --git a/tpke-wasm/examples/browser/webpack.config.js b/tpke-wasm/examples/browser/webpack.config.js new file mode 100644 index 00000000..78076f04 --- /dev/null +++ b/tpke-wasm/examples/browser/webpack.config.js @@ -0,0 +1,12 @@ +const CopyWebpackPlugin = require("copy-webpack-plugin"); +const path = require('path'); + +module.exports = { + entry: "./bootstrap.js", + output: { + path: path.resolve(__dirname, "dist"), + filename: "bootstrap.js", + }, + mode: "development", + plugins: [new CopyWebpackPlugin(["index.html"])], +}; diff --git a/tpke-wasm/examples/browser/yarn.lock b/tpke-wasm/examples/browser/yarn.lock new file mode 100644 index 00000000..4a8dada0 --- /dev/null +++ b/tpke-wasm/examples/browser/yarn.lock @@ -0,0 +1,3826 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/glob@^7.1.1": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/minimatch@*": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" + integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== + +"@types/node@*": + version "18.14.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.0.tgz#94c47b9217bbac49d4a67a967fdcdeed89ebb7d0" + integrity sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A== + +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== + dependencies: + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== + +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== + +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== + +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== + dependencies: + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== + +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== + dependencies: + "@webassemblyjs/ast" "1.9.0" + +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== + +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== + +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/helper-wasm-section" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-opt" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/floating-point-hex-parser" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-code-frame" "1.9.0" + "@webassemblyjs/helper-fsm" "1.9.0" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + "@xtuc/long" "4.2.2" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn@^6.4.1: + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== + +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv@^6.1.0, ajv@^6.10.2: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-colors@^3.0.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" + integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== + +ansi-html-community@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array-flatten@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng== + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== + +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + +assert@^1.1.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + dependencies: + object-assign "^4.1.1" + util "0.10.3" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== + +async-each@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.6.tgz#52f1d9403818c179b7561e11a5d1b77eb2160e77" + integrity sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg== + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@^2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.0.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bluebird@^3.5.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +bonjour@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" + integrity sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg== + dependencies: + array-flatten "^2.1.0" + deep-equal "^1.0.1" + dns-equal "^1.0.0" + dns-txt "^2.0.2" + multicast-dns "^6.0.1" + multicast-dns-service-types "^1.1.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-indexof@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" + integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +buffer@^4.3.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +cacache@^12.0.2, cacache@^12.0.3: + version "12.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" + integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== + dependencies: + bluebird "^3.5.5" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.4" + graceful-fs "^4.1.15" + infer-owner "^1.0.3" + lru-cache "^5.1.1" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.3" + ssri "^6.0.1" + unique-filename "^1.1.1" + y18n "^4.0.0" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + optionalDependencies: + fsevents "^1.2.7" + +chokidar@^3.4.1: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-stream@^1.5.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +connect-history-api-fallback@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" + integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== + +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== + dependencies: + aproba "^1.1.1" + fs-write-stream-atomic "^1.0.8" + iferr "^0.1.5" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.0" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== + +copy-webpack-plugin@^5.0.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz#8a889e1dcafa6c91c6cd4be1ad158f1d3823bae2" + integrity sha512-Uh7crJAco3AjBvgAy9Z75CjK8IG+gxaErro71THQ+vv/bl4HaQcpkexAY8KVW/T6D2W2IRr+couF/knIRkZMIQ== + dependencies: + cacache "^12.0.3" + find-cache-dir "^2.1.0" + glob-parent "^3.1.0" + globby "^7.1.1" + is-glob "^4.0.1" + loader-utils "^1.2.3" + minimatch "^3.0.4" + normalize-path "^3.0.0" + p-limit "^2.2.1" + schema-utils "^1.0.0" + serialize-javascript "^4.0.0" + webpack-log "^2.0.0" + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@^6.0.0, cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + integrity sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A== + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0, debug@^4.1.1: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decode-uri-component@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + +deep-equal@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +default-gateway@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" + integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== + dependencies: + execa "^1.0.0" + ip-regex "^2.1.0" + +define-properties@^1.1.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +del@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" + integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== + dependencies: + "@types/glob" "^7.1.1" + globby "^6.1.0" + is-path-cwd "^2.0.0" + is-path-in-cwd "^2.0.0" + p-map "^2.0.0" + pify "^4.0.1" + rimraf "^2.6.3" + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q== + +detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dir-glob@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" + integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== + dependencies: + path-type "^3.0.0" + +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== + +dns-packet@^1.3.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" + integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== + dependencies: + ip "^1.1.0" + safe-buffer "^5.0.1" + +dns-txt@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" + integrity sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ== + dependencies: + buffer-indexof "^1.0.0" + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +elliptic@^6.5.3: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enhanced-resolve@^4.1.1, enhanced-resolve@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" + integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" + +errno@^0.1.3, errno@~0.1.7: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +esrecurse@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +eventsource@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-2.0.2.tgz#76dfcc02930fb2ff339520b6d290da573a9e8508" + integrity sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw== + dependencies: + homedir-polyfill "^1.0.1" + +express@^4.17.1: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +faye-websocket@^0.11.3, faye-websocket@^0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +figgy-pudding@^3.5.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-cache-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +findup-sync@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" + integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== + dependencies: + detect-file "^1.0.0" + is-glob "^4.0.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + +flush-write-stream@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +follow-redirects@^1.0.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-write-stream-atomic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + integrity sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA== + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^1.2.7: + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== + dependencies: + bindings "^1.5.0" + nan "^2.12.1" + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + +glob-parent@5.1.2, glob-parent@^3.1.0, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg== + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +globby@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" + integrity sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw== + dependencies: + array-union "^1.0.1" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +globby@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" + integrity sha512-yANWAN2DUcBtuus5Cpd+SKROzXHs2iVXFZt/Ykrfz6SAXqacLX25NZpltE+39ceMexYF4TtEadjuSTw8+3wX4g== + dependencies: + array-union "^1.0.1" + dir-glob "^2.0.0" + glob "^7.1.2" + ignore "^3.3.5" + pify "^3.0.0" + slash "^1.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +html-entities@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" + integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== + +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + +http-proxy-middleware@0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" + integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== + dependencies: + http-proxy "^1.17.0" + is-glob "^4.0.0" + lodash "^4.17.11" + micromatch "^3.1.10" + +http-proxy@^1.17.0: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.4: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + integrity sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA== + +ignore@^3.3.5: + version "3.3.10" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== + +import-local@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== + dependencies: + pkg-dir "^3.0.0" + resolve-cwd "^2.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +infer-owner@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + +ini@^1.3.4, ini@^1.3.5: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +internal-ip@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" + integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== + dependencies: + default-gateway "^4.2.0" + ipaddr.js "^1.9.0" + +interpret@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + integrity sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw== + +ip@^1.1.0, ip@^1.1.5: + version "1.1.8" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48" + integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== + +ipaddr.js@1.9.1, ipaddr.js@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-absolute-url@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q== + dependencies: + binary-extensions "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-cwd@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + +is-path-in-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" + integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== + dependencies: + is-path-inside "^2.1.0" + +is-path-inside@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" + integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== + dependencies: + path-is-inside "^1.0.2" + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.0.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== + +is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json5@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + +killable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" + integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +loader-runner@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== + +loader-utils@^1.2.3, loader-utils@^1.4.0: + version "1.4.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" + integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +lodash@^4.17.11, lodash@^4.17.14: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +loglevel@^1.6.8: + version "1.8.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4" + integrity sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== + dependencies: + object-visit "^1.0.0" + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +memory-fs@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mime@^2.4.4: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^3.0.0" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + integrity sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ== + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multicast-dns-service-types@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" + integrity sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ== + +multicast-dns@^6.0.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" + integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== + dependencies: + dns-packet "^1.3.1" + thunky "^1.0.2" + +nan@^2.12.1: + version "2.17.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.5.0, neo-async@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-forge@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" + integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== + +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.1" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.11.0" + vm-browserify "^1.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== + dependencies: + path-key "^2.0.0" + +object-assign@^4.0.1, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== + dependencies: + isobject "^3.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== + dependencies: + isobject "^3.0.1" + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +opn@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" + integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== + dependencies: + is-wsl "^1.1.0" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== + +p-limit@^2.0.0, p-limit@^2.2.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + +p-retry@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" + integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== + dependencies: + retry "^0.12.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@~1.0.5: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +parallel-transform@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== + dependencies: + cyclist "^1.0.1" + inherits "^2.0.3" + readable-stream "^2.1.5" + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + dependencies: + asn1.js "^5.2.0" + browserify-aes "^1.0.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== + +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== + +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + +pbkdf2@^3.0.3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +portfinder@^1.0.26: + version "1.0.32" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" + integrity sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg== + dependencies: + async "^2.6.4" + debug "^3.2.7" + mkdirp "^0.5.6" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== + +punycode@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.2.0: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg== + dependencies: + resolve-from "^3.0.0" + +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg== + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + +rimraf@^2.5.4, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + integrity sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg== + dependencies: + aproba "^1.1.1" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== + dependencies: + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== + +selfsigned@^1.10.8: + version "1.10.14" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.14.tgz#ee51d84d9dcecc61e07e4aba34f229ab525c1574" + integrity sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA== + dependencies: + node-forge "^0.10.0" + +semver@^5.5.0, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" + +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg== + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +sockjs-client@^1.5.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.6.1.tgz#350b8eda42d6d52ddc030c39943364c11dcad806" + integrity sha512-2g0tjOR+fRs0amxENLi/q5TiJTqY+WXFOzb5UwXndlK6TO3U/mirZznpx6w34HVMoc3g7cY24yC/ZMIYnDlfkw== + dependencies: + debug "^3.2.7" + eventsource "^2.0.2" + faye-websocket "^0.11.4" + inherits "^2.0.4" + url-parse "^1.5.10" + +sockjs@^0.3.21: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@~0.5.12: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +ssri@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" + integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== + dependencies: + figgy-pudding "^3.5.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-shift@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +tapable@^1.0.0, tapable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +terser-webpack-plugin@^1.4.3: + version "1.4.5" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" + integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== + dependencies: + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^4.0.0" + source-map "^0.6.1" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" + +terser@^4.1.2: + version "4.8.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.1.tgz#a00e5634562de2239fd404c649051bf6fc21144f" + integrity sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + +timers-browserify@^2.0.4: + version "2.0.12" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== + dependencies: + setimmediate "^1.0.4" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA== + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tpke-wasm@../../pkg: + version "0.1.0-alpha.1" + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== + +url-parse@^1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ== + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ== + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + +watchpack-chokidar2@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" + integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== + dependencies: + chokidar "^2.1.8" + +watchpack@^1.7.4: + version "1.7.5" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" + integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== + dependencies: + graceful-fs "^4.1.2" + neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.1" + watchpack-chokidar2 "^2.0.1" + +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + +webpack-cli@^3.1.0: + version "3.3.12" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" + integrity sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag== + dependencies: + chalk "^2.4.2" + cross-spawn "^6.0.5" + enhanced-resolve "^4.1.1" + findup-sync "^3.0.0" + global-modules "^2.0.0" + import-local "^2.0.0" + interpret "^1.4.0" + loader-utils "^1.4.0" + supports-color "^6.1.0" + v8-compile-cache "^2.1.1" + yargs "^13.3.2" + +webpack-dev-middleware@^3.7.2: + version "3.7.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" + integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== + dependencies: + memory-fs "^0.4.1" + mime "^2.4.4" + mkdirp "^0.5.1" + range-parser "^1.2.1" + webpack-log "^2.0.0" + +webpack-dev-server@^3.1.5: + version "3.11.3" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz#8c86b9d2812bf135d3c9bce6f07b718e30f7c3d3" + integrity sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA== + dependencies: + ansi-html-community "0.0.8" + bonjour "^3.5.0" + chokidar "^2.1.8" + compression "^1.7.4" + connect-history-api-fallback "^1.6.0" + debug "^4.1.1" + del "^4.1.1" + express "^4.17.1" + html-entities "^1.3.1" + http-proxy-middleware "0.19.1" + import-local "^2.0.0" + internal-ip "^4.3.0" + ip "^1.1.5" + is-absolute-url "^3.0.3" + killable "^1.0.1" + loglevel "^1.6.8" + opn "^5.5.0" + p-retry "^3.0.1" + portfinder "^1.0.26" + schema-utils "^1.0.0" + selfsigned "^1.10.8" + semver "^6.3.0" + serve-index "^1.9.1" + sockjs "^0.3.21" + sockjs-client "^1.5.0" + spdy "^4.0.2" + strip-ansi "^3.0.1" + supports-color "^6.1.0" + url "^0.11.0" + webpack-dev-middleware "^3.7.2" + webpack-log "^2.0.0" + ws "^6.2.1" + yargs "^13.3.2" + +webpack-log@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" + integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== + dependencies: + ansi-colors "^3.0.0" + uuid "^3.3.2" + +webpack-sources@^1.4.0, webpack-sources@^1.4.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack@^4.29.3: + version "4.46.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" + integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^4.5.0" + eslint-scope "^4.0.3" + json-parse-better-errors "^1.0.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.3" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.7.4" + webpack-sources "^1.4.1" + +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== + +which@^1.2.14, which@^1.2.9, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +worker-farm@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" + integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== + dependencies: + errno "~0.1.7" + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@^6.2.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e" + integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw== + dependencies: + async-limiter "~1.0.0" + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^13.3.2: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" diff --git a/tpke-wasm/examples/node/README.md b/tpke-wasm/examples/node/README.md index 44878d8b..404272ab 100644 --- a/tpke-wasm/examples/node/README.md +++ b/tpke-wasm/examples/node/README.md @@ -2,6 +2,13 @@ ## Usage +Make sure `pkg` is build with correct target: +```bash +cd ../../ +wasm-pack build --target nodejs +``` + +Install dependencies and run tests: ```bash $ yarn install $ yarn test diff --git a/tpke-wasm/pkg/.gitkeep b/tpke-wasm/pkg/.gitkeep deleted file mode 100644 index e69de29b..00000000 From 0c454347a7e5237d6a9104de85fc7e89a4a844ea Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Tue, 21 Feb 2023 17:10:14 +0100 Subject: [PATCH 34/36] seup wheels ci job for ferveo-python --- .github/workflows/wheels.yml | 139 +++++++++++++++++++++++++++++++++++ ferveo-python/Cargo.toml | 2 +- ferveo-python/setup.py | 2 +- 3 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/wheels.yml diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml new file mode 100644 index 00000000..014267e2 --- /dev/null +++ b/.github/workflows/wheels.yml @@ -0,0 +1,139 @@ +# Adopted from: https://github.com/nucypher/rust-umbral/blob/master/.github/workflows/wheels.yml + +name: Wheels + +on: workflow_dispatch + +jobs: + build_wheels: + name: Build wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, windows-latest, macos-latest, macos-11 ] + + env: + CIBW_BUILD_VERBOSITY: 1 + CIBW_BEFORE_ALL_LINUX: "curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y && yum install -y openssl-devel" + CIBW_BEFORE_BUILD_LINUX: "pip3 install --upgrade keyrings.alt" + CIBW_ARCHS_LINUX: "x86_64" + CIBW_ENVIRONMENT: 'PATH="$PATH:$HOME/.cargo/bin"' + CIBW_SKIP: "cp36-* pp* *-win32 *musllinux*" # only using manylinux to build + + steps: + - uses: actions/checkout@v2 + + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + + - if: runner.os == 'Windows' + run: | + echo 'PATH=/c/Python38:/c/Python38/Scripts:/c/Strawberry/perl/site/bin:/c/Strawberry/perl/bin:/c/Strawberry/c/bin:$PATH' >> $GITHUB_ENV + echo 'RUSTFLAGS=-Ctarget-feature=+crt-static' >> $GITHUB_ENV + echo 'RUSTFLAGS=-Ctarget-feature=+crt-static' >> $GITHUB_ENV + echo 'CIBW_BEFORE_BUILD=python -m pip install --upgrade pip' >> $GITHUB_ENV + - if: runner.os != 'Linux' + name: Setup env when not using docker + run: | + python -m pip install --upgrade wheel setuptools setuptools-rust + - if: runner.os == 'Linux' + name: Set up QEMU + id: qemu + uses: docker/setup-qemu-action@v1 + with: + image: tonistiigi/binfmt:latest + platforms: arm64 + + - uses: actions/setup-python@v2 + name: Install Python + with: + python-version: '3.8' + + - name: Install cibuildwheel + run: | + # Install cibuildwheel from git for CIBW_ARCHS_LINUX support + python -m pip install cibuildwheel==2.9.0 + + - if: runner.os == 'Linux' + run: | + cp -r ./ferveo ./ferveo-python/ferveo + cp -r ./ferveo-common ./ferveo-python/ferveo-common + cp -r ./tpke ./ferveo-python/tpke + + - if: runner.os == 'Linux' + working-directory: ./ferveo-python + name: Relocate dependencies in cargo.toml + run: | + sed -i 's/..\/ferveo/.\/ferveo/g' Cargo.toml + sed -i 's/..\/tpke/.\/tpke/g' Cargo.toml + + - name: Build wheels + working-directory: ./ferveo-python + run: | + pwd + ls -la + cd ferveo-python && python -m cibuildwheel --output-dir wheelhouse + + - uses: actions/upload-artifact@v2 + with: + path: ./ferveo-python/wheelhouse/*.whl + + build_sdist: + name: Build source distribution + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-python@v2 + name: Install Python + with: + python-version: '3.8' + + - name: Install setuptools and setuptools-rust + working-directory: ./ferveo-python + run: | + python -m pip install --upgrade wheel setuptools setuptools-rust + + # Assuming here that the version of the Python bindings + # is matched to the version of the main Rust crate (as it should be at all times), + # and we are running this at a release commit. + - name: Replace the relative path to `ferveo` in Cargo.toml with the specific version + working-directory: ./ferveo-python + run: python replace_version.py relative-to-published + + - name: Build sdist + working-directory: ./ferveo-python + run: python setup.py sdist + + # Roll back the changes + - name: Replace the specific version of `ferveo` in Cargo.toml with the relative path + if: always() + working-directory: ./ferveo-python + run: python replace_version.py published-to-relative + + - uses: actions/upload-artifact@v2 + with: + path: ./ferveo-python/dist/*.tar.gz + + upload_pypi: + needs: [ build_wheels, build_sdist ] + runs-on: ubuntu-latest + + steps: + - uses: actions/download-artifact@v2 + with: + name: artifact + path: dist + - uses: actions/download-artifact@v2 + with: + name: artifact + path: wheelhouse + + - uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: __token__ + password: ${{ secrets.pypi_password }} diff --git a/ferveo-python/Cargo.toml b/ferveo-python/Cargo.toml index 0cc8876d..93cb83bc 100644 --- a/ferveo-python/Cargo.toml +++ b/ferveo-python/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ferveo-python" authors = ["Piotr Roslaniec "] -version = "0.1.0" +version = "0.1.1" edition = "2018" [lib] diff --git a/ferveo-python/setup.py b/ferveo-python/setup.py index 29d57adc..9953bc5f 100644 --- a/ferveo-python/setup.py +++ b/ferveo-python/setup.py @@ -10,7 +10,7 @@ description="Ferveo DKG scheme", long_description=long_description, long_description_content_type="text/markdown", - version="0.1.0", + version="0.1.1", author="Piotr Roslaniec", author_email="p.roslaniec@gmail.com", url="https://github.com/nucypher/ferveo/tree/master/ferveo-python", From 8e6f3912850ad57e89a21c2d6625e64fcd150fa2 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Thu, 23 Feb 2023 13:01:48 +0100 Subject: [PATCH 35/36] fix cargo-udeps error --- Cargo.lock | 116 +++------------------------------------------- ferveo/Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2ab96e73..d469bf64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,7 +110,7 @@ dependencies = [ "ark-serialize", "ark-std", "derivative", - "digest 0.10.6", + "digest", "itertools", "num-bigint", "num-traits", @@ -163,7 +163,7 @@ checksum = "58ea39d00a8a4c832e6f6520e58ccec7bf909c4845863512e9b8656fd47df355" dependencies = [ "ark-serialize-derive", "ark-std", - "digest 0.10.6", + "digest", "num-bigint", ] @@ -247,15 +247,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.3" @@ -289,12 +280,6 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - [[package]] name = "cast" version = "0.3.0" @@ -618,19 +603,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "curve25519-dalek" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - [[package]] name = "cxx" version = "1.0.90" @@ -741,51 +713,16 @@ dependencies = [ "syn", ] -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - [[package]] name = "digest" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "block-buffer 0.10.3", + "block-buffer", "crypto-common", ] -[[package]] -name = "ed25519" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" -dependencies = [ - "serde", - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek", - "ed25519", - "merlin", - "rand 0.7.3", - "serde", - "serde_bytes", - "sha2 0.9.9", - "zeroize", -] - [[package]] name = "either" version = "1.8.1" @@ -814,8 +751,7 @@ dependencies = [ "ark-std", "bincode", "criterion 0.3.6", - "digest 0.10.6", - "ed25519-dalek", + "digest", "either", "ferveo-common", "group-threshold-cryptography", @@ -940,7 +876,7 @@ dependencies = [ "serde", "serde_bytes", "serde_with", - "sha2 0.10.6", + "sha2", "subproductdomain", "thiserror", ] @@ -1106,15 +1042,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "keccak" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" -dependencies = [ - "cpufeatures", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -1204,18 +1131,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" -[[package]] -name = "merlin" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" -dependencies = [ - "byteorder", - "keccak", - "rand_core 0.5.1", - "zeroize", -] - [[package]] name = "miniz_oxide" version = "0.6.2" @@ -1818,19 +1733,6 @@ dependencies = [ "syn", ] -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha2" version = "0.10.6" @@ -1839,15 +1741,9 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest", ] -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" - [[package]] name = "smallvec" version = "1.10.0" diff --git a/ferveo/Cargo.toml b/ferveo/Cargo.toml index a6eac8f3..e551da48 100644 --- a/ferveo/Cargo.toml +++ b/ferveo/Cargo.toml @@ -24,7 +24,6 @@ rand = "0.8" rand_old = { package = "rand", version = "0.7" } # used by benchmarks/pairing.rs either = "1.6.1" miracl_core = "2.3.0" -ed25519-dalek = { version = "1", features = ["serde", "batch"] } serde = { version = "1.0", features = ["derive"] } zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] } serde_bytes = { version = "0.11" } @@ -44,6 +43,7 @@ digest = { version = "0.10.0", features = ["alloc"] } [package.metadata.cargo-udeps.ignore] development = ["pprof"] +build = ["rand_old"] [[example]] name = "pvdkg" From 59ba443ec1b091bf6f94521f6ea6b98f7ab77864 Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Thu, 23 Feb 2023 16:41:42 +0100 Subject: [PATCH 36/36] remove cargo-udeps from ci --- .github/workflows/workspace.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index fa695c91..c95e7fee 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -43,17 +43,6 @@ jobs: with: command: fmt args: --all -- --check - # Switching to nightly here because cargo-udeps-action doesn't work on stable - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - components: clippy - override: true - profile: minimal - - uses: aig787/cargo-udeps-action@v1 - with: - version: 'latest' - args: '--all-targets' test: runs-on: ubuntu-latest