Skip to content

Commit eb453b8

Browse files
committed
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.
1 parent 3ecb5e4 commit eb453b8

File tree

4 files changed

+80
-0
lines changed

4 files changed

+80
-0
lines changed

src/ecdsa/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ mod recovery;
1212
#[cfg_attr(docsrs, doc(cfg(feature = "recovery")))]
1313
pub use self::recovery::{RecoveryId, RecoverableSignature};
1414

15+
#[cfg(feature = "global-context")]
16+
use SECP256K1;
17+
1518
/// An ECDSA signature
1619
#[derive(Copy, Clone, PartialEq, Eq)]
1720
pub struct Signature(pub(crate) ffi::Signature);
@@ -269,6 +272,14 @@ impl Signature {
269272
}
270273
ret
271274
}
275+
276+
/// Verifies an ECDSA signature for `msg` using `pk` and the global [`SECP256K1`] context.
277+
#[inline]
278+
#[cfg(feature = "global-context")]
279+
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
280+
pub fn verify(&self, msg: &Message, pk: &PublicKey) -> Result<(), Error> {
281+
SECP256K1.verify_ecdsa(msg, self, pk)
282+
}
272283
}
273284

274285
impl CPtr for Signature {

src/ecdsa/recovery.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,15 @@ impl RecoverableSignature {
121121
Signature(ret)
122122
}
123123
}
124+
125+
/// Determines the public key for which this [`Signature`] is valid for `msg`. Requires a
126+
/// verify-capable context.
127+
#[inline]
128+
#[cfg(feature = "global-context")]
129+
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
130+
pub fn recover(&self, msg: &Message) -> Result<key::PublicKey, Error> {
131+
SECP256K1.recover_ecdsa(msg, self)
132+
}
124133
}
125134

126135

src/key.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ use Verification;
2828
use constants;
2929
use ffi::{self, CPtr};
3030

31+
#[cfg(feature = "global-context")]
32+
use {Message, ecdsa, SECP256K1};
33+
#[cfg(all(feature = "global-context", feature = "rand-std"))]
34+
use schnorr;
35+
3136
/// Secret 256-bit key used as `x` in an ECDSA signature.
3237
///
3338
/// # Examples
@@ -279,6 +284,14 @@ impl SecretKey {
279284
}
280285
}
281286
}
287+
288+
/// Constructs an ECDSA signature for `msg` using the global [`SECP256K1`] context.
289+
#[inline]
290+
#[cfg(feature = "global-context")]
291+
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
292+
pub fn sign_ecdsa(&self, msg: Message) -> ecdsa::Signature {
293+
SECP256K1.sign_ecdsa(&msg, self)
294+
}
282295
}
283296

284297
#[cfg(feature = "serde")]
@@ -349,6 +362,14 @@ impl PublicKey {
349362
}
350363
}
351364

365+
/// Creates a new public key from a [`SecretKey`] and the global [`SECP256K1`] context.
366+
#[inline]
367+
#[cfg(feature = "global-context")]
368+
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
369+
pub fn from_secret_key_global(sk: &SecretKey) -> PublicKey {
370+
PublicKey::from_secret_key(&SECP256K1, sk)
371+
}
372+
352373
/// Creates a public key directly from a slice.
353374
#[inline]
354375
pub fn from_slice(data: &[u8]) -> Result<PublicKey, Error> {
@@ -738,6 +759,18 @@ impl KeyPair {
738759
}
739760
}
740761

762+
/// Creates a Schnorr [`KeyPair`] directly from a secret key string and the global [`SECP256K1`] context.
763+
///
764+
/// # Errors
765+
///
766+
/// [`Error::InvalidSecretKey`] if corresponding public key for the provided secret key is not even.
767+
#[inline]
768+
#[cfg(feature = "global-context")]
769+
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
770+
pub fn from_seckey_str_global(s: &str) -> Result<KeyPair, Error> {
771+
KeyPair::from_seckey_str(SECP256K1, s)
772+
}
773+
741774
/// Generates a new random secret key.
742775
/// # Examples
743776
///
@@ -768,6 +801,14 @@ impl KeyPair {
768801
}
769802
}
770803

804+
/// Generates a new random secret key using the global [`SECP256K1`] context.
805+
#[inline]
806+
#[cfg(all(feature = "global-context", feature = "rand"))]
807+
#[cfg_attr(docsrs, doc(cfg(all(feature = "global-context", feature = "rand"))))]
808+
pub fn new_global<R: ::rand::Rng + ?Sized>(rng: &mut R) -> KeyPair {
809+
KeyPair::new(SECP256K1, rng)
810+
}
811+
771812
/// Serializes the key pair as a secret key byte value.
772813
#[inline]
773814
pub fn serialize_secret(&self) -> [u8; constants::SECRET_KEY_SIZE] {
@@ -830,6 +871,14 @@ impl KeyPair {
830871
pub fn public_key(&self) -> XOnlyPublicKey {
831872
XOnlyPublicKey::from_keypair(self)
832873
}
874+
875+
/// Constructs an schnorr signature for `msg` using the global [`SECP256K1`] context.
876+
#[inline]
877+
#[cfg(all(feature = "global-context", feature = "rand-std"))]
878+
#[cfg_attr(docsrs, doc(cfg(all(feature = "global-context", feature = "rand-std"))))]
879+
pub fn sign_schnorr(&self, msg: Message) -> schnorr::Signature {
880+
SECP256K1.sign_schnorr(&msg, self)
881+
}
833882
}
834883

835884
impl From<KeyPair> for SecretKey {

src/schnorr.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ use ffi::{self, CPtr};
1313
use {constants, Secp256k1};
1414
use {Message, Signing, Verification, KeyPair, XOnlyPublicKey};
1515

16+
#[cfg(all(feature = "global-context", feature = "rand-std"))]
17+
use SECP256K1;
18+
1619
/// Represents a Schnorr signature.
1720
pub struct Signature([u8; constants::SCHNORRSIG_SIGNATURE_SIZE]);
1821
impl_array_newtype!(Signature, u8, constants::SCHNORRSIG_SIGNATURE_SIZE);
@@ -88,6 +91,14 @@ impl Signature {
8891
_ => Err(Error::InvalidSignature),
8992
}
9093
}
94+
95+
/// Verifies a schnorr signature for `msg` using `pk` and the global [`SECP256K1`] context.
96+
#[inline]
97+
#[cfg(all(feature = "global-context", feature = "rand-std"))]
98+
#[cfg_attr(docsrs, doc(cfg(all(feature = "global-context", feature = "rand-std"))))]
99+
pub fn verify(&self, msg: &Message, pk: &XOnlyPublicKey) -> Result<(), Error> {
100+
SECP256K1.verify_schnorr(self, msg, pk)
101+
}
91102
}
92103

93104
impl<C: Signing> Secp256k1<C> {

0 commit comments

Comments
 (0)