What changed, and why it matters
This commit is a routine internal code reorganization. It moves the PublicKey and PrivateKey type definitions into a private 'encapsulate' module and re-exports them publicly. The fields were already private before this change, so no new access restrictions are introduced. There is no indication this fixes a security bug or changes behavior visible to users of the library.
No security action required. Treat as normal refactoring. Reviewers may verify that downstream code still compiles and that the re-export visibility is identical to the previous top-level pub struct definitions.
Security signals we found
No security-relevant signal: pure encapsulation/reorganization of already-private fields
No new validation or parsing logic introduced
No unsafe code, no secret material exposure, no entropy changes
Evidence from the diff
The diff relocates PublicKey and PrivateKey into an existing mod encapsulate { … } block in bitcoin/src/crypto/key.rs and adds them to the pub use encapsulate::{…, PublicKey, PrivateKey, …} re-export list. The struct fields (compressed, inner, network) remain private. The existing inherent impl blocks are split: constructor/accessor methods move with the structs into the encapsulate module, while legacy/deprecated methods and trait implementations stay in the parent module. No functional changes, no new validation, no new unsafe code, and no security-relevant behavior change is evident.
Changed components
bitcoin/src/crypto/key.rsPublicKey typePrivateKey typeencapsulate submodule re-exportsInspect captured patch +70 / −65
diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs
index 3576c7f2..b0f09d23 100644
--- a/bitcoin/src/crypto/key.rs
+++ b/bitcoin/src/crypto/key.rs
@@ -29,8 +29,8 @@ use crate::taproot::{TapNodeHash, TapTweakHash};
#[rustfmt::skip] // Keep public re-exports separate.
pub use secp256k1::{constants, Parity, Verification};
pub use encapsulate::{
- CompressedPublicKey, Keypair, SerializedXOnlyPublicKey, TweakedKeypair, TweakedPublicKey,
- XOnlyPublicKey,
+ CompressedPublicKey, Keypair, PublicKey, PrivateKey, SerializedXOnlyPublicKey,
+ TweakedKeypair, TweakedPublicKey, XOnlyPublicKey,
};
#[cfg(all(feature = "rand", feature = "std"))]
pub use secp256k1::rand;
@@ -38,6 +38,7 @@ pub use secp256k1::rand;
/// Encapsulation module to provide a clear barrier for construction/destruction of types.
mod encapsulate {
use secp256k1::Parity;
+ use crate::network::NetworkKind;
/// A Bitcoin Schnorr X-only public key used for BIP-0340 signatures.
///
@@ -94,6 +95,36 @@ mod encapsulate {
pub fn to_inner(self) -> secp256k1::Keypair { self.0 }
}
+ /// A Bitcoin ECDSA public key.
+ #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+ pub struct PublicKey {
+ /// Whether this public key should be serialized as compressed.
+ compressed: bool,
+ /// The actual ECDSA key.
+ inner: secp256k1::PublicKey,
+ }
+
+ impl PublicKey {
+ /// Constructs a new compressed ECDSA public key from the provided secp256k1 public key.
+ pub fn from_secp(key: impl Into<secp256k1::PublicKey>) -> Self {
+ Self { compressed: true, inner: key.into() }
+ }
+
+ /// Constructs a new uncompressed (legacy) ECDSA public key from the provided secp256k1 public
+ /// key.
+ pub fn from_secp_uncompressed(key: impl Into<secp256k1::PublicKey>) -> Self {
+ Self { compressed: false, inner: key.into() }
+ }
+
+ /// Returns the inner secp256k1 public key.
+ #[inline]
+ pub fn to_inner(self) -> secp256k1::PublicKey { self.inner }
+
+ /// Returns whether this public key should be serialized as compressed.
+ #[inline]
+ pub fn compressed(&self) -> bool { self.compressed }
+ }
+
/// An always-compressed Bitcoin ECDSA public key.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CompressedPublicKey(secp256k1::PublicKey);
@@ -108,6 +139,43 @@ mod encapsulate {
pub fn to_inner(self) -> secp256k1::PublicKey { self.0 }
}
+ /// A Bitcoin ECDSA private key.
+ #[derive(Debug, Copy, Clone, PartialEq, Eq)]
+ pub struct PrivateKey {
+ /// Whether this private key should be serialized as compressed.
+ compressed: bool,
+ /// The network kind on which this key should be used.
+ network: NetworkKind,
+ /// The actual ECDSA key.
+ inner: secp256k1::SecretKey,
+ }
+
+ impl PrivateKey {
+ /// Constructs a new compressed ECDSA private key from the provided secp256k1 private
+ /// key and the specified network.
+ pub fn from_secp(key: secp256k1::SecretKey, network: impl Into<NetworkKind>) -> Self {
+ Self { compressed: true, network: network.into(), inner: key }
+ }
+
+ /// Constructs a new uncompressed (legacy) ECDSA private key from the provided secp256k1
+ /// private key and the specified network.
+ pub fn from_secp_uncompressed(key: secp256k1::SecretKey, network: impl Into<NetworkKind>) -> Self {
+ Self { compressed: false, network: network.into(), inner: key }
+ }
+
+ /// Returns a reference to the inner secp256k1 secret key.
+ #[inline]
+ pub fn as_inner(&self) -> &secp256k1::SecretKey { &self.inner }
+
+ /// Returns whether this private key should be serialized as compressed.
+ #[inline]
+ pub fn compressed(&self) -> bool { self.compressed }
+
+ /// Returns the [`NetworkKind`] of this key.
+ #[inline]
+ pub fn network(&self) -> NetworkKind { self.network }
+ }
+
/// Tweaked BIP-0340 X-coord-only public key.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
@@ -400,15 +468,6 @@ impl From<Keypair> for secp256k1::PublicKey {
fn from(kp: Keypair) -> Self { kp.to_public_key().to_inner() }
}
-/// A Bitcoin ECDSA public key.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct PublicKey {
- /// Whether this public key should be serialized as compressed.
- compressed: bool,
- /// The actual ECDSA key.
- inner: secp256k1::PublicKey,
-}
-
impl PublicKey {
/// Constructs a new compressed ECDSA public key from the provided generic secp256k1 public key.
#[deprecated(since = "TBD", note = "use `from_secp` instead")]
@@ -423,25 +482,6 @@ impl PublicKey {
Self::from_secp_uncompressed(key)
}
- /// Constructs a new compressed ECDSA public key from the provided secp256k1 public key.
- pub fn from_secp(key: impl Into<secp256k1::PublicKey>) -> Self {
- Self { compressed: true, inner: key.into() }
- }
-
- /// Constructs a new uncompressed (legacy) ECDSA public key from the provided secp256k1 public
- /// key.
- pub fn from_secp_uncompressed(key: impl Into<secp256k1::PublicKey>) -> Self {
- Self { compressed: false, inner: key.into() }
- }
-
- /// Returns the inner secp256k1 public key.
- #[inline]
- pub fn to_inner(self) -> secp256k1::PublicKey { self.inner }
-
- /// Returns whether this public key should be serialized as compressed.
- #[inline]
- pub fn compressed(&self) -> bool { self.compressed }
-
fn with_serialized<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
if self.compressed() {
f(&self.to_inner().serialize())
@@ -797,17 +837,6 @@ impl From<&CompressedPublicKey> for WPubkeyHash {
fn from(key: &CompressedPublicKey) -> Self { key.wpubkey_hash() }
}
-/// A Bitcoin ECDSA private key.
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub struct PrivateKey {
- /// Whether this private key should be serialized as compressed.
- compressed: bool,
- /// The network kind on which this key should be used.
- network: NetworkKind,
- /// The actual ECDSA key.
- inner: secp256k1::SecretKey,
-}
-
impl PrivateKey {
/// Constructs a new compressed ECDSA private key using the secp256k1 algorithm and
/// a secure random number generator.
@@ -817,30 +846,6 @@ impl PrivateKey {
Self::from_secp(secret_key, network.into())
}
- /// Constructs a new compressed ECDSA private key from the provided secp256k1 private
- /// key and the specified network.
- pub fn from_secp(key: secp256k1::SecretKey, network: impl Into<NetworkKind>) -> Self {
- Self { compressed: true, network: network.into(), inner: key }
- }
-
- /// Constructs a new uncompressed (legacy) ECDSA private key from the provided secp256k1
- /// private key and the specified network.
- pub fn from_secp_uncompressed(key: secp256k1::SecretKey, network: impl Into<NetworkKind>) -> Self {
- Self { compressed: false, network: network.into(), inner: key }
- }
-
- /// Returns a reference to the inner secp256k1 secret key.
- #[inline]
- pub fn as_inner(&self) -> &secp256k1::SecretKey { &self.inner }
-
- /// Returns whether this private key should be serialized as compressed.
- #[inline]
- pub fn compressed(&self) -> bool { self.compressed }
-
- /// Returns the [`NetworkKind`] of this key.
- #[inline]
- pub fn network(&self) -> NetworkKind { self.network }
-
/// Constructs a new public key from this private key.
pub fn public_key(&self) -> PublicKey {
match self.compressed() {
Why this scored 17/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.