Replace uses of secp XOnlyPublicKey with parity access
What changed, and why it matters
This is a small internal cleanup change in the rust-bitcoin library. It swaps some low-level uses of one public-key type for another equivalent type that now carries extra parity information. There is no indication this fixes a security bug or changes behavior visible to users in a risky way.
No security action needed. Treat as routine refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit replaces direct calls to secp256k1’s XOnlyPublicKey::x_only_public_key() and parity extraction with the library’s own bitcoin::XOnlyPublicKey, which now embeds parity. The changes are in sighash tests and PSBT key-lookup code/tests. The logic remains the same: keys are still normalized to even parity where required. No security-relevant behavior change is evident from the diff.
Changed components
bitcoin/src/crypto/sighash.rsbitcoin/src/psbt/mod.rsInspect captured patch +10 / −11
diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs
index 0c3ed66e..e991d2f5 100644
--- a/bitcoin/src/crypto/sighash.rs
+++ b/bitcoin/src/crypto/sighash.rs
@@ -2035,8 +2035,7 @@ mod tests {
let key_spend_sig = tweaked_keypair
.raw_bip340_sign_with_aux_randomness(&sighash.to_byte_array(), &[0u8; 32]);
- // Only compare the inner key, not the parity
- assert_eq!(expected.internal_pubkey.to_inner(), internal_key.to_inner());
+ assert_eq!(expected.internal_pubkey.with_parity(internal_key.parity()), internal_key);
assert_eq!(expected.sig_msg, sig_msg.to_lower_hex_string());
assert_eq!(expected.sig_hash, sighash);
assert_eq!(expected_hash_ty, hash_ty);
diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs
index 5068643f..5cd6e2bc 100644
--- a/bitcoin/src/psbt/mod.rs
+++ b/bitcoin/src/psbt/mod.rs
@@ -900,13 +900,13 @@ impl GetKey for $map<XOnlyPublicKey, PrivateKey> {
match key_request {
KeyRequest::XOnlyPubkey(xonly) => Ok(self.get(xonly).cloned()),
KeyRequest::Pubkey(pk) => {
- let (xonly, parity) = pk.to_inner().x_only_public_key();
+ let xonly = XOnlyPublicKey::from(*pk);
if let Some(mut priv_key) = self.get(&XOnlyPublicKey::from(xonly)).cloned() {
let computed_pk = priv_key.to_public_key();
- let (_, computed_parity) = computed_pk.to_inner().x_only_public_key();
+ let computed_parity = XOnlyPublicKey::from(computed_pk).parity();
- if computed_parity != parity {
+ if computed_parity != xonly.parity() {
priv_key = priv_key.negate();
}
@@ -2379,27 +2379,27 @@ mod tests {
use crate::psbt::{GetKey, KeyRequest};
let (mut priv_key, mut pk) = gen_keys();
- let (xonly, parity) = pk.to_inner().x_only_public_key();
+ let xonly = XOnlyPublicKey::from(pk);
let mut pubkey_map: HashMap<PublicKey, PrivateKey> = HashMap::new();
- if parity == secp256k1::Parity::Even {
+ if xonly.parity() == secp256k1::Parity::Even {
priv_key = priv_key.negate();
pk = priv_key.to_public_key();
}
pubkey_map.insert(pk, priv_key);
- let req_result = pubkey_map.get_key(&KeyRequest::XOnlyPubkey(xonly.into())).unwrap();
+ let req_result = pubkey_map.get_key(&KeyRequest::XOnlyPubkey(xonly)).unwrap();
let retrieved_key = req_result.unwrap();
let retrieved_pub_key = retrieved_key.to_public_key();
- let (retrieved_xonly, retrieved_parity) = retrieved_pub_key.to_inner().x_only_public_key();
+ let retrieved_xonly = XOnlyPublicKey::from(retrieved_pub_key);
- assert_eq!(xonly, retrieved_xonly);
+ assert_eq!(xonly, retrieved_xonly.with_parity(xonly.parity()));
assert_eq!(
- retrieved_parity,
+ retrieved_xonly.parity(),
secp256k1::Parity::Even,
"Key should be normalized to have even parity, even when original had odd parity"
);
Why this scored 13/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.