Merge pull request #224 from sgeisler/2020-07-global-context
Add an optional global, static context
This commit is contained in:
commit
c6ab14bcbe
|
@ -43,6 +43,9 @@ script:
|
|||
- cargo test --verbose --features="rand rand-std"
|
||||
- cargo test --verbose --features="rand serde"
|
||||
- cargo test --verbose --features="rand serde recovery endomorphism"
|
||||
- if [ ${TRAVIS_RUST_VERSION} != "1.22.0" ]; then
|
||||
cargo test --verbose --features global-context;
|
||||
fi
|
||||
- cargo build --verbose
|
||||
- cargo test --verbose
|
||||
- cargo build --verbose --release
|
||||
|
|
|
@ -29,6 +29,7 @@ rand-std = ["rand/std"]
|
|||
recovery = ["secp256k1-sys/recovery"]
|
||||
endomorphism = ["secp256k1-sys/endomorphism"]
|
||||
lowmemory = ["secp256k1-sys/lowmemory"]
|
||||
global-context = ["std", "rand"]
|
||||
|
||||
# Use this feature to not compile the bundled libsecp256k1 C symbols,
|
||||
# but use external ones. Use this only if you know what you are doing!
|
||||
|
|
|
@ -9,6 +9,38 @@ use Secp256k1;
|
|||
#[cfg(feature = "std")]
|
||||
pub use self::std_only::*;
|
||||
|
||||
#[cfg(feature = "global-context")]
|
||||
/// Module implementing a singleton pattern for a global `Secp256k1` context
|
||||
pub mod global {
|
||||
use std::ops::Deref;
|
||||
use std::sync::Once;
|
||||
use ::{Secp256k1, All};
|
||||
|
||||
/// Proxy struct for global `SECP256K1` context
|
||||
pub struct GlobalContext {
|
||||
__private: (),
|
||||
}
|
||||
|
||||
/// A global, static context to avoid repeatedly creating contexts where one can't be passed
|
||||
pub static SECP256K1: &GlobalContext = &GlobalContext { __private: () };
|
||||
|
||||
impl Deref for GlobalContext {
|
||||
type Target = Secp256k1<All>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
static ONCE: Once = Once::new();
|
||||
static mut CONTEXT: Option<Secp256k1<All>> = None;
|
||||
ONCE.call_once(|| unsafe {
|
||||
let mut ctx = Secp256k1::new();
|
||||
ctx.randomize(&mut rand::thread_rng());
|
||||
CONTEXT = Some(ctx);
|
||||
});
|
||||
unsafe { CONTEXT.as_ref().unwrap() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A trait for all kinds of Context's that Lets you define the exact flags and a function to deallocate memory.
|
||||
/// It shouldn't be possible to implement this for types outside this crate.
|
||||
pub unsafe trait Context : private::Sealed {
|
||||
|
|
21
src/lib.rs
21
src/lib.rs
|
@ -179,6 +179,9 @@ use core::marker::PhantomData;
|
|||
use core::ops::Deref;
|
||||
use ffi::CPtr;
|
||||
|
||||
#[cfg(feature = "global-context")]
|
||||
pub use context::global::SECP256K1;
|
||||
|
||||
#[cfg(feature = "bitcoin_hashes")]
|
||||
use bitcoin_hashes::Hash;
|
||||
|
||||
|
@ -1138,6 +1141,24 @@ mod tests {
|
|||
assert_tokens(&sig.readable(), &[Token::BorrowedStr(SIG_STR)]);
|
||||
}
|
||||
|
||||
#[cfg(feature = "global-context")]
|
||||
#[test]
|
||||
fn test_global_context() {
|
||||
use super::SECP256K1;
|
||||
|
||||
let sk_data = hex!("e6dd32f8761625f105c39a39f19370b3521d845a12456d60ce44debd0a362641");
|
||||
let sk = SecretKey::from_slice(&sk_data).unwrap();
|
||||
let msg_data = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d");
|
||||
let msg = Message::from_slice(&msg_data).unwrap();
|
||||
|
||||
// Check usage as explicit parameter
|
||||
let pk = PublicKey::from_secret_key(&SECP256K1, &sk);
|
||||
|
||||
// Check usage as self
|
||||
let sig = SECP256K1.sign(&msg, &sk);
|
||||
assert!(SECP256K1.verify(&msg, &sig, &pk).is_ok());
|
||||
}
|
||||
|
||||
// For WASM, just run through our general tests in this file all at once.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
extern crate wasm_bindgen_test;
|
||||
|
|
Loading…
Reference in New Issue