From bec8929b77f97f1470e724ae9985cf4fbb6066c4 Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Tue, 8 Feb 2022 06:11:05 +0000 Subject: [PATCH] Add global context API Our API often involves a `Secp256k1` parameter, when users enable the `global-context` feature they must then pass `SECP256K1` into these functions. This is kind of clunky since the global is by definition available everywhere. Make the API more ergonomic for `global-context` builds by adding various API functions/methods that use the global context implicitly. --- src/ecdsa/mod.rs | 10 ++++++++++ src/ecdsa/recovery.rs | 8 ++++++++ src/key.rs | 19 +++++++++++++++++++ src/schnorr.rs | 10 ++++++++++ 4 files changed, 47 insertions(+) diff --git a/src/ecdsa/mod.rs b/src/ecdsa/mod.rs index f7baa71a3..059444c11 100644 --- a/src/ecdsa/mod.rs +++ b/src/ecdsa/mod.rs @@ -12,6 +12,9 @@ mod recovery; #[cfg_attr(docsrs, doc(cfg(feature = "recovery")))] pub use self::recovery::{RecoveryId, RecoverableSignature}; +#[cfg(feature = "global-context")] +use SECP256K1; + /// An ECDSA signature #[derive(Copy, Clone, PartialEq, Eq)] pub struct Signature(pub(crate) ffi::Signature); @@ -269,6 +272,13 @@ impl Signature { } ret } + + /// Verifies an ECDSA signature for `msg` using `pk` and the global [`SECP256K1`] context. + #[cfg(feature = "global-context")] + #[cfg_attr(docsrs, doc(cfg(feature = "global-context")))] + pub fn verify(&self, msg: &Message, pk: &PublicKey) -> Result<(), Error> { + SECP256K1.verify_ecdsa(msg, self, pk) + } } impl CPtr for Signature { diff --git a/src/ecdsa/recovery.rs b/src/ecdsa/recovery.rs index ca367def9..e45f6e823 100644 --- a/src/ecdsa/recovery.rs +++ b/src/ecdsa/recovery.rs @@ -121,6 +121,14 @@ impl RecoverableSignature { Signature(ret) } } + + /// Determines the public key for which this [`Signature`] is valid for `msg`. Requires a + /// verify-capable context. + #[cfg(feature = "global-context")] + #[cfg_attr(docsrs, doc(cfg(feature = "global-context")))] + pub fn recover(&self, msg: &Message) -> Result { + SECP256K1.recover_ecdsa(msg, self) + } } diff --git a/src/key.rs b/src/key.rs index 562f02e2f..7c9bcdb5f 100644 --- a/src/key.rs +++ b/src/key.rs @@ -28,6 +28,11 @@ use Verification; use constants; use ffi::{self, CPtr}; +#[cfg(feature = "global-context")] +use {Message, ecdsa, SECP256K1}; +#[cfg(all(feature = "global-context", feature = "rand-std"))] +use schnorr; + /// Secret 256-bit key used as `x` in an ECDSA signature. /// /// # Examples @@ -279,6 +284,13 @@ impl SecretKey { } } } + + /// Constructs an ECDSA signature for `msg` using the global [`SECP256K1`] context. + #[cfg(feature = "global-context")] + #[cfg_attr(docsrs, doc(cfg(feature = "global-context")))] + pub fn sign_ecdsa(&self, msg: Message) -> ecdsa::Signature { + SECP256K1.sign_ecdsa(&msg, self) + } } #[cfg(feature = "serde")] @@ -832,6 +844,13 @@ impl KeyPair { pub fn public_key(&self) -> XOnlyPublicKey { XOnlyPublicKey::from_keypair(self) } + + /// Constructs an schnorr signature for `msg` using the global [`SECP256K1`] context. + #[cfg(all(feature = "global-context", feature = "rand-std"))] + #[cfg_attr(docsrs, doc(cfg(feature = "global-context")))] + pub fn sign_schnorr(&self, msg: Message) -> schnorr::Signature { + SECP256K1.sign_schnorr(&msg, self) + } } impl From for SecretKey { diff --git a/src/schnorr.rs b/src/schnorr.rs index c709573e5..839b063ac 100644 --- a/src/schnorr.rs +++ b/src/schnorr.rs @@ -13,6 +13,9 @@ use ffi::{self, CPtr}; use {constants, Secp256k1}; use {Message, Signing, Verification, KeyPair, XOnlyPublicKey}; +#[cfg(all(feature = "global-context", feature = "rand-std"))] +use SECP256K1; + /// Represents a Schnorr signature. pub struct Signature([u8; constants::SCHNORRSIG_SIGNATURE_SIZE]); impl_array_newtype!(Signature, u8, constants::SCHNORRSIG_SIGNATURE_SIZE); @@ -88,6 +91,13 @@ impl Signature { _ => Err(Error::InvalidSignature), } } + + /// Verifies a schnorr signature for `msg` using `pk` and the global [`SECP256K1`] context. + #[cfg(all(feature = "global-context", feature = "rand-std"))] + #[cfg_attr(docsrs, doc(cfg(feature = "global-context")))] + pub fn verify(&self, msg: &Message, pk: &XOnlyPublicKey) -> Result<(), Error> { + SECP256K1.verify_schnorr(self, msg, pk) + } } impl Secp256k1 {