Merge pull request #224 from sgeisler/2020-07-global-context

Add an optional global, static context
This commit is contained in:
Andrew Poelstra 2020-08-07 18:13:09 +00:00 committed by GitHub
commit c6ab14bcbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 0 deletions

View File

@ -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

View File

@ -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!

View File

@ -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 {

View File

@ -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;