From 9626533678ae0de41b7e8d6a75c1ebe717076493 Mon Sep 17 00:00:00 2001 From: LLFourn Date: Fri, 5 Jul 2024 13:51:04 +1000 Subject: [PATCH] [compat] Add compatibility with secp256k1 v0.29.0 --- ecdsa_fun/Cargo.toml | 3 +- ecdsa_fun/src/libsecp_compat.rs | 17 +++++ schnorr_fun/Cargo.toml | 3 +- schnorr_fun/src/libsecp_compat.rs | 17 +++++ secp256kfun/Cargo.toml | 6 +- secp256kfun/src/lib.rs | 6 +- secp256kfun/src/libsecp_compat.rs | 109 +++++++++++++++++++++++++++++- 7 files changed, 154 insertions(+), 7 deletions(-) diff --git a/ecdsa_fun/Cargo.toml b/ecdsa_fun/Cargo.toml index 9eccd7cf..720b9d06 100644 --- a/ecdsa_fun/Cargo.toml +++ b/ecdsa_fun/Cargo.toml @@ -34,9 +34,10 @@ required-features = ["libsecp_compat"] [features] default = ["std"] -libsecp_compat = ["secp256kfun/libsecp_compat", "libsecp_compat_0_28"] +libsecp_compat = ["libsecp_compat_0_28", "secp256kfun/libsecp_compat"] libsecp_compat_0_27 = ["secp256kfun/libsecp_compat_0_27"] libsecp_compat_0_28 = ["secp256kfun/libsecp_compat_0_28"] +libsecp_compat_0_29 = ["secp256kfun/libsecp_compat_0_29"] std = ["alloc"] alloc = ["secp256kfun/alloc", "sigma_fun?/alloc" ] serde = ["secp256kfun/serde","sigma_fun?/serde"] diff --git a/ecdsa_fun/src/libsecp_compat.rs b/ecdsa_fun/src/libsecp_compat.rs index 5d2213dc..98a38b1e 100644 --- a/ecdsa_fun/src/libsecp_compat.rs +++ b/ecdsa_fun/src/libsecp_compat.rs @@ -31,3 +31,20 @@ mod v0_28 { } } } + +#[cfg(feature = "libsecp_compat_0_29")] +mod v0_29 { + use crate::{fun::secp256k1_0_29::ecdsa, Signature}; + + impl From for ecdsa::Signature { + fn from(sig: Signature) -> Self { + ecdsa::Signature::from_compact(sig.to_bytes().as_ref()).unwrap() + } + } + + impl From for Signature { + fn from(sig: ecdsa::Signature) -> Self { + Signature::from_bytes(sig.serialize_compact()).unwrap() + } + } +} diff --git a/schnorr_fun/Cargo.toml b/schnorr_fun/Cargo.toml index e4be82c6..939f8ad3 100644 --- a/schnorr_fun/Cargo.toml +++ b/schnorr_fun/Cargo.toml @@ -42,9 +42,10 @@ alloc = ["secp256kfun/alloc" ] std = ["alloc", "secp256kfun/std"] bincode = ["secp256kfun/bincode"] serde = ["secp256kfun/serde"] -libsecp_compat = ["secp256kfun/libsecp_compat", "libsecp_compat_0_28"] +libsecp_compat = ["libsecp_compat_0_29", "secp256kfun/libsecp_compat"] libsecp_compat_0_27 = ["secp256kfun/libsecp_compat_0_27"] libsecp_compat_0_28 = ["secp256kfun/libsecp_compat_0_28"] +libsecp_compat_0_29 = ["secp256kfun/libsecp_compat_0_29"] proptest = ["secp256kfun/proptest"] share_backup = ["dep:bech32"] diff --git a/schnorr_fun/src/libsecp_compat.rs b/schnorr_fun/src/libsecp_compat.rs index 4dc7c724..c5018d1e 100644 --- a/schnorr_fun/src/libsecp_compat.rs +++ b/schnorr_fun/src/libsecp_compat.rs @@ -31,3 +31,20 @@ mod v0_28 { } } } + +#[cfg(feature = "libsecp_compat_0_29")] +mod v0_29 { + use secp256kfun::secp256k1_0_29::schnorr; + + impl From for schnorr::Signature { + fn from(sig: crate::Signature) -> Self { + schnorr::Signature::from_slice(sig.to_bytes().as_ref()).unwrap() + } + } + + impl From for crate::Signature { + fn from(sig: schnorr::Signature) -> Self { + crate::Signature::from_bytes(*sig.as_ref()).unwrap() + } + } +} diff --git a/secp256kfun/Cargo.toml b/secp256kfun/Cargo.toml index 0cb3de4a..bd88af5e 100644 --- a/secp256kfun/Cargo.toml +++ b/secp256kfun/Cargo.toml @@ -27,6 +27,7 @@ bincode = { version = "2.0.0-rc.3", optional = true, default-features = false, f secp256k1_0_27 = { package = "secp256k1", version = "0.27", optional = true, default-features = false } secp256k1_0_28 = { package = "secp256k1", version = "0.28", optional = true, default-features = false } +secp256k1_0_29 = { package = "secp256k1", version = "0.29", optional = true, default-features = false } [dev-dependencies] @@ -42,13 +43,14 @@ wasm-bindgen-test = "0.3" [features] default = ["std"] -libsecp_compat = ["libsecp_compat_0_28"] +libsecp_compat = ["libsecp_compat_0_29"] alloc = [ "serde?/alloc", "digest/alloc", "bincode?/alloc", "secp256k1_0_27?/alloc", "secp256k1_0_28?/alloc", +"secp256k1_0_29?/alloc", ] std = ["alloc", "subtle/std", "digest/std", "bincode?/std", "secp256k1_0_27?/std", "secp256k1_0_28?/std"] serde = [ @@ -56,10 +58,12 @@ serde = [ "bincode?/serde", "secp256k1_0_27?/serde", "secp256k1_0_28?/serde", +"secp256k1_0_29?/serde", ] libsecp_compat_0_27 = [ "dep:secp256k1_0_27" ] libsecp_compat_0_28 = [ "dep:secp256k1_0_28" ] +libsecp_compat_0_29 = [ "dep:secp256k1_0_29" ] [[bench]] diff --git a/secp256kfun/src/lib.rs b/secp256kfun/src/lib.rs index dfb5b3c2..d22c6aa6 100755 --- a/secp256kfun/src/lib.rs +++ b/secp256kfun/src/lib.rs @@ -91,5 +91,9 @@ pub extern crate secp256k1_0_27; /// Re-export `secp256k1` pub extern crate secp256k1_0_28; +#[cfg(feature = "libsecp_compat_0_29")] +/// Re-export `secp256k1` +pub extern crate secp256k1_0_29; + #[cfg(feature = "libsecp_compat")] -pub use secp256k1_0_28 as secp256k1; +pub use secp256k1_0_29 as secp256k1; diff --git a/secp256kfun/src/libsecp_compat.rs b/secp256kfun/src/libsecp_compat.rs index 4a6107b1..ae1da394 100644 --- a/secp256kfun/src/libsecp_compat.rs +++ b/secp256kfun/src/libsecp_compat.rs @@ -1,3 +1,106 @@ +#[cfg(feature = "libsecp_compat_0_27")] +mod v0_27 { + use crate::{marker::*, Point, Scalar}; + use secp256k1::{PublicKey, SecretKey, XOnlyPublicKey}; + use secp256k1_0_27 as secp256k1; + + impl From for SecretKey { + fn from(scalar: Scalar) -> Self { + SecretKey::from_slice(scalar.to_bytes().as_ref()).unwrap() + } + } + + impl From for Scalar { + fn from(sk: SecretKey) -> Self { + Scalar::from_slice(&sk[..]) + .unwrap() + .non_zero() + .expect("SecretKey is never zero") + } + } + + impl From> for secp256k1::Scalar { + fn from(value: Scalar) -> Self { + secp256k1::Scalar::from_be_bytes(value.to_bytes()).unwrap() + } + } + + impl From for Scalar { + fn from(value: secp256k1::Scalar) -> Self { + Scalar::from_bytes(value.to_be_bytes()).unwrap() + } + } + + impl From for Point { + fn from(pk: PublicKey) -> Self { + Point::::from_bytes(pk.serialize()).unwrap() + } + } + + impl From for PublicKey { + fn from(pk: Point) -> Self { + PublicKey::from_slice(pk.to_bytes().as_ref()).unwrap() + } + } + + impl From> for XOnlyPublicKey { + fn from(point: Point) -> Self { + XOnlyPublicKey::from_slice(point.to_xonly_bytes().as_ref()).unwrap() + } + } + + impl From for Point { + fn from(pk: XOnlyPublicKey) -> Self { + Point::from_xonly_bytes(pk.serialize()).unwrap() + } + } + + #[cfg(test)] + mod test { + use super::*; + use core::str::FromStr; + #[cfg(feature = "proptest")] + use proptest::prelude::*; + + #[test] + fn public_key() { + let pk = PublicKey::from_str("0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8").unwrap(); + let point = Point::from(pk); + assert_eq!(pk.serialize().as_ref(), point.to_bytes().as_ref()); + } + + #[cfg(feature = "proptest")] + proptest! { + + #[test] + fn prop_public_key(first_byte in 0u8..10, x_bytes in any::<[u8;32]>()) { + let mut bytes = [0u8;33]; + bytes[0] = first_byte; + bytes[1..33].copy_from_slice(&x_bytes[..]); + let pk = PublicKey::from_slice(&bytes[..]).ok(); + let point = Point::<_,Public, >::from_bytes(bytes); + assert_eq!(pk.map(|pk| pk.serialize()), point.map(|point| point.to_bytes())); + } + + #[test] + fn prop_secret_key(bytes in any::<[u8;32]>()) { + let sk = SecretKey::from_slice(&bytes[..]).unwrap(); + let scalar = Scalar::from(sk); + assert_eq!(&sk[..], scalar.to_bytes().as_ref()); + } + + + + #[test] + fn scalar_roundtrip(scalar in any::>()) { + let secp_scalar = secp256k1::Scalar::from(scalar); + let rt_scalar = Scalar::from(secp_scalar); + assert_eq!(rt_scalar, scalar); + } + } + } +} + #[cfg(feature = "libsecp_compat_0_28")] mod v0_28 { use crate::{marker::*, Point, Scalar}; @@ -101,11 +204,11 @@ mod v0_28 { } } -#[cfg(feature = "libsecp_compat_0_27")] -mod v0_27 { +#[cfg(feature = "libsecp_compat_0_29")] +mod v0_29 { use crate::{marker::*, Point, Scalar}; use secp256k1::{PublicKey, SecretKey, XOnlyPublicKey}; - use secp256k1_0_27 as secp256k1; + use secp256k1_0_29 as secp256k1; impl From for SecretKey { fn from(scalar: Scalar) -> Self {