1use core::marker::PhantomData;
4use core::mem::ManuallyDrop;
5use core::ptr::NonNull;
6
7#[cfg(feature = "alloc")]
8pub use self::alloc_only::{All, SignOnly, VerifyOnly};
9use crate::ffi::types::{c_uint, c_void, AlignedType};
10use crate::ffi::{self, CPtr};
11use crate::{Error, Secp256k1};
12
13#[cfg(all(feature = "global-context", feature = "std"))]
14pub mod global {
16
17 use std::ops::Deref;
18 use std::sync::Once;
19
20 use crate::{All, Secp256k1};
21
22 #[derive(Debug, Copy, Clone)]
24 pub struct GlobalContext {
25 __private: (),
26 }
27
28 pub static SECP256K1: &GlobalContext = &GlobalContext { __private: () };
39
40 impl Deref for GlobalContext {
41 type Target = Secp256k1<All>;
42
43 #[allow(unused_mut)] fn deref(&self) -> &Self::Target {
45 static ONCE: Once = Once::new();
46 static mut CONTEXT: Option<Secp256k1<All>> = None;
47 ONCE.call_once(|| unsafe {
48 let mut ctx = Secp256k1::new();
49 #[cfg(all(
50 not(target_arch = "wasm32"),
51 feature = "rand-std",
52 not(feature = "global-context-less-secure")
53 ))]
54 {
55 ctx.randomize(&mut rand::thread_rng());
56 }
57 CONTEXT = Some(ctx);
58 });
59 unsafe { CONTEXT.as_ref().unwrap() }
60 }
61 }
62}
63
64pub unsafe trait Context: private::Sealed {
71 const FLAGS: c_uint;
73 const DESCRIPTION: &'static str;
75 unsafe fn deallocate(ptr: *mut u8, size: usize);
81}
82
83pub trait Signing: Context {}
85
86pub trait Verification: Context {}
88
89#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
91pub struct SignOnlyPreallocated<'buf> {
92 phantom: PhantomData<&'buf ()>,
93}
94
95#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
97pub struct VerifyOnlyPreallocated<'buf> {
98 phantom: PhantomData<&'buf ()>,
99}
100
101#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
103pub struct AllPreallocated<'buf> {
104 phantom: PhantomData<&'buf ()>,
105}
106
107mod private {
108 use super::*;
109 pub trait Sealed {}
110
111 impl<'buf> Sealed for AllPreallocated<'buf> {}
112 impl<'buf> Sealed for VerifyOnlyPreallocated<'buf> {}
113 impl<'buf> Sealed for SignOnlyPreallocated<'buf> {}
114}
115
116#[cfg(feature = "alloc")]
117mod alloc_only {
118 use core::marker::PhantomData;
119 use core::ptr::NonNull;
120
121 use super::private;
122 use crate::alloc::alloc;
123 use crate::ffi::types::{c_uint, c_void};
124 use crate::ffi::{self};
125 use crate::{AlignedType, Context, Secp256k1, Signing, Verification};
126
127 impl private::Sealed for SignOnly {}
128 impl private::Sealed for All {}
129 impl private::Sealed for VerifyOnly {}
130
131 const ALIGN_TO: usize = core::mem::align_of::<AlignedType>();
132
133 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
135 pub enum SignOnly {}
136
137 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
139 pub enum VerifyOnly {}
140
141 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
143 pub enum All {}
144
145 impl Signing for SignOnly {}
146 impl Signing for All {}
147
148 impl Verification for VerifyOnly {}
149 impl Verification for All {}
150
151 unsafe impl Context for SignOnly {
152 const FLAGS: c_uint = ffi::SECP256K1_START_SIGN;
153 const DESCRIPTION: &'static str = "signing only";
154
155 unsafe fn deallocate(ptr: *mut u8, size: usize) {
156 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
157 alloc::dealloc(ptr, layout);
158 }
159 }
160
161 unsafe impl Context for VerifyOnly {
162 const FLAGS: c_uint = ffi::SECP256K1_START_VERIFY;
163 const DESCRIPTION: &'static str = "verification only";
164
165 unsafe fn deallocate(ptr: *mut u8, size: usize) {
166 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
167 alloc::dealloc(ptr, layout);
168 }
169 }
170
171 unsafe impl Context for All {
172 const FLAGS: c_uint = VerifyOnly::FLAGS | SignOnly::FLAGS;
173 const DESCRIPTION: &'static str = "all capabilities";
174
175 unsafe fn deallocate(ptr: *mut u8, size: usize) {
176 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
177 alloc::dealloc(ptr, layout);
178 }
179 }
180
181 impl<C: Context> Secp256k1<C> {
182 #[cfg_attr(not(feature = "rand-std"), allow(clippy::let_and_return, unused_mut))]
199 pub fn gen_new() -> Secp256k1<C> {
200 #[cfg(target_arch = "wasm32")]
201 ffi::types::sanity_checks_for_wasm();
202
203 let size = unsafe { ffi::secp256k1_context_preallocated_size(C::FLAGS) };
204 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
205 let ptr = unsafe { alloc::alloc(layout) };
206 let ptr = NonNull::new(ptr as *mut c_void)
207 .unwrap_or_else(|| alloc::handle_alloc_error(layout));
208
209 #[allow(unused_mut)] let mut ctx = Secp256k1 {
211 ctx: unsafe { ffi::secp256k1_context_preallocated_create(ptr, C::FLAGS) },
212 phantom: PhantomData,
213 };
214
215 #[cfg(all(
216 not(target_arch = "wasm32"),
217 feature = "rand-std",
218 not(feature = "global-context-less-secure")
219 ))]
220 {
221 ctx.randomize(&mut rand::thread_rng());
222 }
223
224 #[allow(clippy::let_and_return)] ctx
226 }
227 }
228
229 impl Secp256k1<All> {
230 pub fn new() -> Secp256k1<All> { Secp256k1::gen_new() }
236 }
237
238 impl Secp256k1<SignOnly> {
239 pub fn signing_only() -> Secp256k1<SignOnly> { Secp256k1::gen_new() }
245 }
246
247 impl Secp256k1<VerifyOnly> {
248 pub fn verification_only() -> Secp256k1<VerifyOnly> { Secp256k1::gen_new() }
254 }
255
256 impl Default for Secp256k1<All> {
257 fn default() -> Self { Self::new() }
258 }
259
260 impl<C: Context> Clone for Secp256k1<C> {
261 fn clone(&self) -> Secp256k1<C> {
262 let size = unsafe { ffi::secp256k1_context_preallocated_clone_size(self.ctx.as_ptr()) };
263 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
264 let ptr = unsafe { alloc::alloc(layout) };
265 let ptr = NonNull::new(ptr as *mut c_void)
266 .unwrap_or_else(|| alloc::handle_alloc_error(layout));
267
268 Secp256k1 {
269 ctx: unsafe { ffi::secp256k1_context_preallocated_clone(self.ctx.as_ptr(), ptr) },
270 phantom: PhantomData,
271 }
272 }
273 }
274}
275
276impl<'buf> Signing for SignOnlyPreallocated<'buf> {}
277impl<'buf> Signing for AllPreallocated<'buf> {}
278
279impl<'buf> Verification for VerifyOnlyPreallocated<'buf> {}
280impl<'buf> Verification for AllPreallocated<'buf> {}
281
282unsafe impl<'buf> Context for SignOnlyPreallocated<'buf> {
283 const FLAGS: c_uint = ffi::SECP256K1_START_SIGN;
284 const DESCRIPTION: &'static str = "signing only";
285
286 unsafe fn deallocate(_ptr: *mut u8, _size: usize) {
287 }
289}
290
291unsafe impl<'buf> Context for VerifyOnlyPreallocated<'buf> {
292 const FLAGS: c_uint = ffi::SECP256K1_START_VERIFY;
293 const DESCRIPTION: &'static str = "verification only";
294
295 unsafe fn deallocate(_ptr: *mut u8, _size: usize) {
296 }
298}
299
300unsafe impl<'buf> Context for AllPreallocated<'buf> {
301 const FLAGS: c_uint = SignOnlyPreallocated::FLAGS | VerifyOnlyPreallocated::FLAGS;
302 const DESCRIPTION: &'static str = "all capabilities";
303
304 unsafe fn deallocate(_ptr: *mut u8, _size: usize) {
305 }
307}
308
309pub unsafe trait PreallocatedContext<'a> {}
318
319unsafe impl<'buf> PreallocatedContext<'buf> for AllPreallocated<'buf> {}
320unsafe impl<'buf> PreallocatedContext<'buf> for SignOnlyPreallocated<'buf> {}
321unsafe impl<'buf> PreallocatedContext<'buf> for VerifyOnlyPreallocated<'buf> {}
322
323impl<'buf, C: Context + PreallocatedContext<'buf>> Secp256k1<C> {
324 pub fn preallocated_gen_new(buf: &'buf mut [AlignedType]) -> Result<Secp256k1<C>, Error> {
326 #[cfg(target_arch = "wasm32")]
327 ffi::types::sanity_checks_for_wasm();
328
329 if buf.len() < Self::preallocate_size_gen() {
330 return Err(Error::NotEnoughMemory);
331 }
332 let buf = unsafe { NonNull::new_unchecked(buf.as_mut_c_ptr() as *mut c_void) };
334
335 Ok(Secp256k1 {
336 ctx: unsafe { ffi::secp256k1_context_preallocated_create(buf, AllPreallocated::FLAGS) },
337 phantom: PhantomData,
338 })
339 }
340}
341
342impl<'buf> Secp256k1<AllPreallocated<'buf>> {
343 pub fn preallocated_new(
345 buf: &'buf mut [AlignedType],
346 ) -> Result<Secp256k1<AllPreallocated<'buf>>, Error> {
347 Secp256k1::preallocated_gen_new(buf)
348 }
349 pub fn preallocate_size() -> usize { Self::preallocate_size_gen() }
351
352 pub unsafe fn from_raw_all(
371 raw_ctx: NonNull<ffi::Context>,
372 ) -> ManuallyDrop<Secp256k1<AllPreallocated<'buf>>> {
373 ManuallyDrop::new(Secp256k1 { ctx: raw_ctx, phantom: PhantomData })
374 }
375}
376
377impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
378 pub fn preallocated_signing_only(
380 buf: &'buf mut [AlignedType],
381 ) -> Result<Secp256k1<SignOnlyPreallocated<'buf>>, Error> {
382 Secp256k1::preallocated_gen_new(buf)
383 }
384
385 #[inline]
387 pub fn preallocate_signing_size() -> usize { Self::preallocate_size_gen() }
388
389 pub unsafe fn from_raw_signing_only(
395 raw_ctx: NonNull<ffi::Context>,
396 ) -> ManuallyDrop<Secp256k1<SignOnlyPreallocated<'buf>>> {
397 ManuallyDrop::new(Secp256k1 { ctx: raw_ctx, phantom: PhantomData })
398 }
399}
400
401impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
402 pub fn preallocated_verification_only(
404 buf: &'buf mut [AlignedType],
405 ) -> Result<Secp256k1<VerifyOnlyPreallocated<'buf>>, Error> {
406 Secp256k1::preallocated_gen_new(buf)
407 }
408
409 #[inline]
411 pub fn preallocate_verification_size() -> usize { Self::preallocate_size_gen() }
412
413 pub unsafe fn from_raw_verification_only(
419 raw_ctx: NonNull<ffi::Context>,
420 ) -> ManuallyDrop<Secp256k1<VerifyOnlyPreallocated<'buf>>> {
421 ManuallyDrop::new(Secp256k1 { ctx: raw_ctx, phantom: PhantomData })
422 }
423}