Skip to content

Commit

Permalink
Enable tests without HD wallets support
Browse files Browse the repository at this point in the history
  • Loading branch information
survived committed Jan 12, 2024
1 parent a2450c5 commit 7dba6e6
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 58 deletions.
33 changes: 30 additions & 3 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ on:
branches: [ "m" ]
pull_request:
branches: [ "*" ]
# schedule:
# - cron: '0 5 * * *'

env:
CARGO_TERM_COLOR: always
Expand All @@ -21,15 +19,44 @@ jobs:
with:
cache-on-failure: "true"
- name: Build
run: cargo build --release
run: cargo build --release --all-features
- uses: actions/upload-artifact@v3
with:
name: benchmark-tool
path: target/release/measure_perf
# Run tests without HD wallets support
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: "true"
- name: Run tests
run: cargo test -r
# Run tests including HD wallets support
test-hd:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: "true"
- name: Run tests
run: cargo test -r --all-features
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Check formatting
run: cargo fmt --all -- --check
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: "true"
- name: Run clippy
run: cargo clippy --all --lib --exclude cggmp21-tests -- --no-deps -D clippy::all -D clippy::unwrap_used -D clippy::expect_used
- name: Run clippy tests
Expand Down
25 changes: 18 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 11 additions & 2 deletions tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cggmp21 = { path = "../cggmp21", features = ["all-curves", "spof", "hd-wallets"] }
cggmp21 = { path = "../cggmp21", features = ["all-curves", "spof"] }

anyhow = "1"
bpaf = "0.7"
Expand Down Expand Up @@ -39,5 +39,14 @@ url = "2.4"

[dev-dependencies]
generic-tests = "0.1"
test-case = "2.2"
test-case = "3"

[features]
hd-wallets = ["cggmp21/hd-wallets"]

[[bin]]
name = "precompute_shares"
required-features = ["hd-wallets"]

[[bin]]
name = "measure_perf"
19 changes: 19 additions & 0 deletions tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,22 @@ pub fn convert_from_stark_scalar(
let bytes = x.to_bytes_be();
generic_ec::Scalar::from_be_bytes(bytes).context("Can't read bytes")
}

#[cfg(feature = "hd-wallets")]
pub fn random_derivation_path<E: Curve>(
rng: &mut impl rand::RngCore,
epub: &cggmp21::slip_10::ExtendedPublicKey<E>,
) -> (Vec<u32>, generic_ec::Point<E>) {
use rand::Rng;

let len = rng.gen_range(1..=3);
let path = std::iter::repeat_with(|| rng.gen_range(0..cggmp21::slip_10::H))
.take(len)
.collect::<Vec<_>>();
let child_epub = cggmp21::slip_10::try_derive_child_public_key_with_path(
epub,
path.iter().copied().map(TryInto::try_into),
)
.unwrap();
(path, child_epub.public_key)
}
5 changes: 5 additions & 0 deletions tests/tests/key_refresh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ mod generic {
let shares = cggmp21_tests::CACHED_SHARES
.get_shares::<E, SecurityLevel128>(None, n, true)
.expect("retrieve cached shares");

#[cfg(feature = "hd-wallets")]
assert!(shares[0].chain_code.is_some());

let mut primes = cggmp21_tests::CACHED_PRIMES.iter();

// Perform refresh
Expand Down Expand Up @@ -74,6 +77,8 @@ mod generic {
shares[0].core.shared_public_key
);
}

#[cfg(feature = "hd-wallets")]
for key_share in &key_shares {
assert_eq!(key_share.chain_code, shares[0].chain_code);
}
Expand Down
56 changes: 39 additions & 17 deletions tests/tests/keygen.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#[generic_tests::define(attrs(tokio::test, test_case::case))]
#[generic_tests::define(attrs(tokio::test, test_case::case, cfg_attr))]
mod generic {
use generic_ec::{Curve, Point};
use rand::{seq::SliceRandom, Rng, SeedableRng};
Expand All @@ -17,12 +17,15 @@ mod generic {
#[test_case::case(7, false, false; "n7")]
#[test_case::case(10, false, false; "n10")]
#[test_case::case(10, true, false; "n10-reliable")]
#[test_case::case(3, false, true; "n3-hd")]
#[test_case::case(5, false, true; "n5-hd")]
#[test_case::case(7, false, true; "n7-hd")]
#[test_case::case(10, false, true; "n10-hd")]
#[cfg_attr(feature = "hd-wallets", test_case::case(3, false, true; "n3-hd"))]
#[cfg_attr(feature = "hd-wallets", test_case::case(5, false, true; "n5-hd"))]
#[cfg_attr(feature = "hd-wallets", test_case::case(7, false, true; "n7-hd"))]
#[cfg_attr(feature = "hd-wallets", test_case::case(10, false, true; "n10-hd"))]
#[tokio::test]
async fn keygen_works<E: Curve>(n: u16, reliable_broadcast: bool, hd_wallet: bool) {
#[cfg(not(feature = "hd-wallets"))]
assert!(!hd_wallet);

let mut rng = DevRng::new();

let mut simulation = Simulation::<NonThresholdMsg<E, SecurityLevel128, Sha256>>::new();
Expand All @@ -36,11 +39,13 @@ mod generic {
let mut party_rng = ChaCha20Rng::from_seed(rng.gen());

outputs.push(async move {
cggmp21::keygen(eid, i, n)
.enforce_reliable_broadcast(reliable_broadcast)
.hd_wallet(hd_wallet)
.start(&mut party_rng, party)
.await
let keygen =
cggmp21::keygen(eid, i, n).enforce_reliable_broadcast(reliable_broadcast);

#[cfg(feature = "hd-wallets")]
let keygen = keygen.hd_wallet(hd_wallet);

keygen.start(&mut party_rng, party).await
})
}

Expand All @@ -61,26 +66,35 @@ mod generic {
key_shares[0].shared_public_key,
key_shares[0].public_shares.iter().sum::<Point<E>>()
);

#[cfg(feature = "hd-wallets")]
if hd_wallet {
assert!(key_shares[0].chain_code.is_some());
for key_share in &key_shares[1..] {
assert_eq!(key_share.chain_code, key_shares[0].chain_code);
}
} else {
for key_share in &key_shares {
assert_eq!(key_share.chain_code, None);
}
}
}

#[test_case::case(2, 3, false, false; "t2n3")]
#[test_case::case(3, 5, false, false; "t3n5")]
#[test_case::case(3, 5, true, false; "t3n5-reliable")]
#[test_case::case(2, 3, false, true; "t2n3-hd")]
#[test_case::case(3, 5, false, true; "t3n5-hd")]
#[cfg_attr(feature = "hd-wallets", test_case::case(2, 3, false, true; "t2n3-hd"))]
#[cfg_attr(feature = "hd-wallets", test_case::case(3, 5, false, true; "t3n5-hd"))]
#[tokio::test]
async fn threshold_keygen_works<E: Curve>(
t: u16,
n: u16,
reliable_broadcast: bool,
hd_wallet: bool,
) {
#[cfg(not(feature = "hd-wallets"))]
assert!(!hd_wallet);

let mut rng = DevRng::new();

let mut simulation = Simulation::<ThresholdMsg<E, SecurityLevel128, Sha256>>::new();
Expand All @@ -94,12 +108,14 @@ mod generic {
let mut party_rng = ChaCha20Rng::from_seed(rng.gen());

outputs.push(async move {
cggmp21::keygen(eid, i, n)
let keygen = cggmp21::keygen(eid, i, n)
.enforce_reliable_broadcast(reliable_broadcast)
.set_threshold(t)
.hd_wallet(hd_wallet)
.start(&mut party_rng, party)
.await
.set_threshold(t);

#[cfg(feature = "hd-wallets")]
let keygen = keygen.hd_wallet(hd_wallet);

keygen.start(&mut party_rng, party).await
})
}

Expand All @@ -116,11 +132,17 @@ mod generic {
key_share.public_shares[usize::from(i)]
);
}

#[cfg(feature = "hd-wallets")]
if hd_wallet {
assert!(key_shares[0].chain_code.is_some());
for key_share in &key_shares[1..] {
assert_eq!(key_share.chain_code, key_shares[0].chain_code);
}
} else {
for key_share in &key_shares {
assert_eq!(key_share.chain_code, None);
}
}

// Choose `t` random key shares and reconstruct a secret key
Expand Down
40 changes: 24 additions & 16 deletions tests/tests/pipeline.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#[generic_tests::define(attrs(tokio::test, test_case::case))]
mod generic {
use generic_ec::{Curve, Point};
use rand::{seq::SliceRandom, Rng};
use rand::{seq::SliceRandom, Rng, RngCore};
use rand_dev::DevRng;
use round_based::simulation::Simulation;
use sha2::Sha256;
Expand Down Expand Up @@ -34,6 +34,9 @@ mod generic {
where
E: Curve,
{
#[cfg(not(feature = "hd-wallets"))]
assert!(!hd_enabled);

let mut simulation = Simulation::<ThresholdMsg<E, SecurityLevel128, Sha256>>::new();

let eid: [u8; 32] = rng.gen();
Expand All @@ -45,11 +48,12 @@ mod generic {
let mut party_rng = rng.fork();

outputs.push(async move {
cggmp21::keygen(eid, i, n)
.set_threshold(t)
.hd_wallet(hd_enabled)
.start(&mut party_rng, party)
.await
let keygen = cggmp21::keygen(eid, i, n).set_threshold(t);

#[cfg(feature = "hd-wallets")]
let keygen = keygen.hd_wallet(hd_enabled);

keygen.start(&mut party_rng, party).await
})
}

Expand Down Expand Up @@ -98,24 +102,24 @@ mod generic {
E: Curve,
Point<E>: generic_ec::coords::HasAffineX<E>,
{
use rand::RngCore;
#[cfg(not(feature = "hd-wallets"))]
assert!(!random_derivation_path);

let t = shares[0].min_signers();
let n = shares.len().try_into().unwrap();

#[cfg(feature = "hd-wallets")]
let (derivation_path, public_key) = if random_derivation_path {
let len = rng.gen_range(1..=3);
let path = std::iter::repeat_with(|| rng.gen_range(0..=cggmp21::slip_10::H))
.take(len)
.collect::<Vec<u32>>();
let public_key = shares[0]
.derive_child_public_key(path.iter().copied())
.unwrap()
.public_key;
(Some(path), public_key)
let (path, child_pub) = cggmp21_tests::random_derivation_path(
rng,
&shares[0].extended_public_key().unwrap(),
);
(Some(path), child_pub)
} else {
(None, shares[0].shared_public_key)
};
#[cfg(not(feature = "hd-wallets"))]
let public_key = shares[0].shared_public_key;

let mut simulation = Simulation::<cggmp21::signing::msg::Msg<E, Sha256>>::new();

Expand All @@ -138,10 +142,14 @@ mod generic {
for (i, share) in (0..).zip(participants_shares) {
let party = simulation.add_party();
let mut party_rng = rng.fork();

#[cfg(feature = "hd-wallets")]
let derivation_path = derivation_path.clone();

outputs.push(async move {
let signing = cggmp21::signing(eid, i, participants, share);

#[cfg(feature = "hd-wallets")]
let signing = if let Some(derivation_path) = derivation_path {
signing.set_derivation_path(derivation_path).unwrap()
} else {
Expand Down
Loading

0 comments on commit 7dba6e6

Please sign in to comment.