Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix feature gating #520

Merged
merged 1 commit into from
Nov 18, 2022

Conversation

tcharding
Copy link
Member

Currently we have a few problems with our feature gating, attempt to audit all feature gating and fix it by doing:

  1. Do not enable features on optional dependencies (rand and bitcoin-hashes) in dev-dependencies, doing so hides broken feature gating in unit tests.
  2. Do not use unnecessary feature combinations when one feature enables another e.g. any(feature = "std", feature = "alloc").
  3. Enable "std" from "rand-std" and "bitcoin-std" (and fix features gating as for point 2).
  4. Clean up code around rand::thread_rng, this is part of this patch because thread_rng requires the "rand-std" feature.
  5. Clean up CI test script to test each feature individually now that "rand-std" and "bitcoin-hashes-std" enable "std".

Currently we have a few problems with our feature gating, attempt to
audit all feature gating and fix it by doing:

1. Do not enable features on optional dependencies (`rand` and
   `bitcoin-hashes`) in dev-dependencies, doing so hides broken feature
   gating in unit tests.
2. Do not use unnecessary feature combinations when one feature enables
   another e.g. `any(feature = "std", feature = "alloc")`.
3. Enable "std" from "rand-std" and "bitcoin-std" (and fix features
   gating as for point 2).
4. Clean up code around `rand::thread_rng`, this is part of this patch
   because `thread_rng` requires the "rand-std" feature.
5. Clean up CI test script to test each feature individually now that
   "rand-std" and "bitcoin-hashes-std" enable "std".
Copy link
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 9c74855

@apoelstra
Copy link
Member

Will wait on @Kixunil to sanity-check before merging. This is a big PR but it's almost entirely mechanical and all the "real" changes are in Cargo.toml.

@tcharding
Copy link
Member Author

Will wait on @Kixunil to sanity-check before merging. This is a big PR but it's almost entirely mechanical and all the "real" changes are in Cargo.toml.

And I could easily have missed some places, I was relying on grep heavily to find lines of code that needed patching.

Copy link
Collaborator

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 9c74855

Very nice cleanup!

All of my suggestions are intended for possible future PRs.

@@ -46,10 +46,8 @@ bitcoin_hashes = { version = "0.11", default-features = false, optional = true }
rand = { version = "0.8", default-features = false, optional = true }

[dev-dependencies]
rand = "0.8"
rand_core = "0.6"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FTR, IIRC I had WIP changes that add rand_core feature so this one would have to go too. But it's OK now.

/// # #[cfg(all(feature = "std", feature = "rand-std"))] {
/// # use secp256k1::Secp256k1;
/// # #[cfg(feature = "rand-std")] {
/// # use secp256k1::{rand, Secp256k1};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this PR but this looks very confusing - it looks as if #[cfg] was controlling use, not the whole block. If we don't want to indent it I suggest we put { on the next line - this is unusual in Rust but much more readable in this case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. The old formatting was chosen with "this line will be hidden" in mind.

I have a mild preference for indenting vs putting { on the next line.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its already laborious to write example code in comments because of zero tooling support, we should be careful what we choose because we (I) will have to go back and change every example in the whole codebase.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, then let's do { on the next line since that's easiest :P and say that this is a very low priority thing.

let mut ret = [0u8; 32];
rng.fill(&mut ret);
ret
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is completely OK for this PR but I don't like non-generic 32_bytes much. For the future I was thinking of some alternative designs: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3123fb72993eabdeeb4a51eb2558be88

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is only available within the crate, where we routinely need 32 uniformly random bytes and never need any other quantity of differently-random bytes.

use crate::ffi::types::AlignedType;
use crate::ffi::{self};
#[cfg(feature = "alloc")]
use crate::{ffi, PublicKey, Secp256k1, SecretKey};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC these do not require alloc but only tests requiring alloc happen to use them, right?

It's not very readable but the only somewhat reasonable idea beyond adding a comment that comes to my mind is having test_std, test_alloc, test_rand... etc modules and the modules have appropriate cfg. Maybe not having same cfgs multiple times is good enough benefit for it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a pretty common pattern in test modules to have feature-gated imports because there are feature-gated tests.

#[cfg_attr(docsrs, doc(cfg(feature = "rand-std")))]
pub fn random() -> Self { Self::random_custom(rand::thread_rng()) }

/// Generates a random scalar using supplied RNG
#[cfg(any(test, feature = "rand"))]
#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
pub fn random_custom<R: rand::Rng>(mut rng: R) -> Self {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I should've implemented Distribution<Scalar> for Standard. 🤦‍♂️

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ITYM for Uniform, but honestly this seems like more complexity (and reading rand docs) (and hoping they never change) than it's worth.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for both Standard and Uniform. If rand is still too far away from stabilizing maybe we should just put it off until then.

@apoelstra
Copy link
Member

Thanks for your review and (somewhat hesitant) ACK! We'll address things in followup PRs.

@apoelstra apoelstra merged commit 29c0549 into rust-bitcoin:master Nov 18, 2022
@tcharding
Copy link
Member Author

Thanks fellas, feels like the feature gating saga is going to be an ongoing one :)

@Kixunil
Copy link
Collaborator

Kixunil commented Nov 18, 2022

Should we release a new version so that we unblock development in bitcoin?

@apoelstra
Copy link
Member

I'd like to get #518 in as well since I believe it is also semver-breaking.

@Kixunil
Copy link
Collaborator

Kixunil commented Nov 19, 2022

Oh, yes, we had "remove deprecated" commits. Would it make sense to backport this for point release?

@apoelstra
Copy link
Member

I think so. Normally changes to feature flags are breaking but I think this is purely additive (except for dev-dependencies). Similarly I think all the changes to feature-gating of functionality is purely additive (things are now available that didn't use to be).

Because it touches so many LOC it'd be a real pain to backport, I think. In particular #499 will be really annoying to backport past :).

I think it'd be less work to get #518 in and then cut a release -- it's almost ready.

@Kixunil
Copy link
Collaborator

Kixunil commented Nov 20, 2022

Oh, OK. Yes, this change is backwards-compatible.

@apoelstra
Copy link
Member

Ok, 518 is in. We can just do a major release and pull that into rust-bitcoin I think.

@apoelstra
Copy link
Member

cc @tcharding can you open a release PR so that I can ack and merge it?

@tcharding
Copy link
Member Author

Sure thing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants