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_attr(feature = "std", path = "internal_std.rs")]
14#[cfg_attr(not(feature = "std"), path = "internal_nostd.rs")]
15mod internal;
16
17#[cfg(not(feature = "std"))]
18mod spinlock;
19
20pub use internal::{rerandomize_global_context, with_global_context, with_raw_global_context};
21
22#[cfg(all(feature = "global-context", feature = "std"))]
23pub mod global {
25
26 use std::ops::Deref;
27 use std::sync::Once;
28
29 use crate::{All, Secp256k1};
30
31 #[derive(Debug, Copy, Clone)]
33 pub struct GlobalContext {
34 __private: (),
35 }
36
37 pub static SECP256K1: &GlobalContext = &GlobalContext { __private: () };
42
43 impl Deref for GlobalContext {
44 type Target = Secp256k1<All>;
45
46 #[allow(unused_mut)] #[allow(static_mut_refs)] fn deref(&self) -> &Self::Target {
50 static ONCE: Once = Once::new();
51 static mut CONTEXT: Option<Secp256k1<All>> = None;
52 ONCE.call_once(|| unsafe {
53 CONTEXT = Some(Secp256k1::new());
54 });
55 unsafe { CONTEXT.as_ref().unwrap() }
56 }
57 }
58}
59
60pub unsafe trait Context: private::Sealed {
67 const FLAGS: c_uint;
69 const DESCRIPTION: &'static str;
71 unsafe fn deallocate(ptr: *mut u8, size: usize);
77}
78
79pub trait Signing: Context {}
81
82pub trait Verification: Context {}
84
85#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
87pub struct SignOnlyPreallocated<'buf> {
88 phantom: PhantomData<&'buf ()>,
89}
90
91#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
93pub struct VerifyOnlyPreallocated<'buf> {
94 phantom: PhantomData<&'buf ()>,
95}
96
97#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
99pub struct AllPreallocated<'buf> {
100 phantom: PhantomData<&'buf ()>,
101}
102
103mod private {
104 use super::*;
105 pub trait Sealed {}
106
107 impl Sealed for AllPreallocated<'_> {}
108 impl Sealed for VerifyOnlyPreallocated<'_> {}
109 impl Sealed for SignOnlyPreallocated<'_> {}
110}
111
112#[cfg(feature = "alloc")]
113mod alloc_only {
114 use core::marker::PhantomData;
115 use core::ptr::NonNull;
116
117 use super::private;
118 use crate::alloc::alloc;
119 use crate::ffi::types::{c_uint, c_void};
120 use crate::ffi::{self};
121 use crate::{AlignedType, Context, Secp256k1, Signing, Verification};
122
123 impl private::Sealed for SignOnly {}
124 impl private::Sealed for All {}
125 impl private::Sealed for VerifyOnly {}
126
127 const ALIGN_TO: usize = core::mem::align_of::<AlignedType>();
128
129 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
131 pub enum SignOnly {}
132
133 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
135 pub enum VerifyOnly {}
136
137 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
139 pub enum All {}
140
141 impl Signing for SignOnly {}
142 impl Signing for All {}
143
144 impl Verification for VerifyOnly {}
145 impl Verification for All {}
146
147 unsafe impl Context for SignOnly {
148 const FLAGS: c_uint = ffi::SECP256K1_START_SIGN;
149 const DESCRIPTION: &'static str = "signing only";
150
151 unsafe fn deallocate(ptr: *mut u8, size: usize) {
152 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
153 alloc::dealloc(ptr, layout);
154 }
155 }
156
157 unsafe impl Context for VerifyOnly {
158 const FLAGS: c_uint = ffi::SECP256K1_START_VERIFY;
159 const DESCRIPTION: &'static str = "verification only";
160
161 unsafe fn deallocate(ptr: *mut u8, size: usize) {
162 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
163 alloc::dealloc(ptr, layout);
164 }
165 }
166
167 unsafe impl Context for All {
168 const FLAGS: c_uint = VerifyOnly::FLAGS | SignOnly::FLAGS;
169 const DESCRIPTION: &'static str = "all capabilities";
170
171 unsafe fn deallocate(ptr: *mut u8, size: usize) {
172 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
173 alloc::dealloc(ptr, layout);
174 }
175 }
176
177 impl<C: Context> Secp256k1<C> {
178 #[cfg_attr(
197 not(all(feature = "rand", feature = "std")),
198 allow(clippy::let_and_return, unused_mut)
199 )]
200 pub fn gen_new() -> Secp256k1<C> {
201 #[cfg(target_arch = "wasm32")]
202 ffi::types::sanity_checks_for_wasm();
203
204 let size = unsafe { ffi::secp256k1_context_preallocated_size(C::FLAGS) };
205 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
206 let ptr = unsafe { alloc::alloc(layout) };
207 let ptr = NonNull::new(ptr as *mut c_void)
208 .unwrap_or_else(|| alloc::handle_alloc_error(layout));
209
210 #[allow(unused_mut)] let mut ctx = Secp256k1 {
212 ctx: unsafe { ffi::secp256k1_context_preallocated_create(ptr, C::FLAGS) },
213 phantom: PhantomData,
214 };
215
216 #[cfg(all(
217 not(target_arch = "wasm32"),
218 feature = "rand",
219 feature = "std",
220 not(feature = "global-context-less-secure")
221 ))]
222 {
223 ctx.randomize(&mut rand::rng());
224 }
225
226 #[allow(clippy::let_and_return)] ctx
228 }
229 }
230
231 impl Secp256k1<All> {
232 pub fn new() -> Secp256k1<All> { Secp256k1::gen_new() }
239 }
240
241 impl Secp256k1<SignOnly> {
242 pub fn signing_only() -> Secp256k1<SignOnly> { Secp256k1::gen_new() }
249 }
250
251 impl Secp256k1<VerifyOnly> {
252 pub fn verification_only() -> Secp256k1<VerifyOnly> { Secp256k1::gen_new() }
259 }
260
261 impl Default for Secp256k1<All> {
262 fn default() -> Self { Self::new() }
263 }
264
265 impl<C: Context> Clone for Secp256k1<C> {
266 fn clone(&self) -> Secp256k1<C> {
267 let size = unsafe { ffi::secp256k1_context_preallocated_clone_size(self.ctx.as_ptr()) };
268 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
269 let ptr = unsafe { alloc::alloc(layout) };
270 let ptr = NonNull::new(ptr as *mut c_void)
271 .unwrap_or_else(|| alloc::handle_alloc_error(layout));
272
273 Secp256k1 {
274 ctx: unsafe { ffi::secp256k1_context_preallocated_clone(self.ctx.as_ptr(), ptr) },
275 phantom: PhantomData,
276 }
277 }
278 }
279}
280
281impl Signing for SignOnlyPreallocated<'_> {}
282impl Signing for AllPreallocated<'_> {}
283
284impl Verification for VerifyOnlyPreallocated<'_> {}
285impl Verification for AllPreallocated<'_> {}
286
287unsafe impl Context for SignOnlyPreallocated<'_> {
288 const FLAGS: c_uint = ffi::SECP256K1_START_SIGN;
289 const DESCRIPTION: &'static str = "signing only";
290
291 unsafe fn deallocate(_ptr: *mut u8, _size: usize) {
292 }
294}
295
296unsafe impl Context for VerifyOnlyPreallocated<'_> {
297 const FLAGS: c_uint = ffi::SECP256K1_START_VERIFY;
298 const DESCRIPTION: &'static str = "verification only";
299
300 unsafe fn deallocate(_ptr: *mut u8, _size: usize) {
301 }
303}
304
305unsafe impl Context for AllPreallocated<'_> {
306 const FLAGS: c_uint = SignOnlyPreallocated::FLAGS | VerifyOnlyPreallocated::FLAGS;
307 const DESCRIPTION: &'static str = "all capabilities";
308
309 unsafe fn deallocate(_ptr: *mut u8, _size: usize) {
310 }
312}
313
314pub unsafe trait PreallocatedContext<'a> {}
323
324unsafe impl<'buf> PreallocatedContext<'buf> for AllPreallocated<'buf> {}
325unsafe impl<'buf> PreallocatedContext<'buf> for SignOnlyPreallocated<'buf> {}
326unsafe impl<'buf> PreallocatedContext<'buf> for VerifyOnlyPreallocated<'buf> {}
327
328impl<'buf, C: Context + PreallocatedContext<'buf>> Secp256k1<C> {
329 pub fn preallocated_gen_new(buf: &'buf mut [AlignedType]) -> Result<Secp256k1<C>, Error> {
331 #[cfg(target_arch = "wasm32")]
332 ffi::types::sanity_checks_for_wasm();
333
334 if buf.len() < Self::preallocate_size_gen() {
335 return Err(Error::NotEnoughMemory);
336 }
337 let buf = unsafe { NonNull::new_unchecked(buf.as_mut_c_ptr() as *mut c_void) };
339
340 Ok(Secp256k1 {
341 ctx: unsafe { ffi::secp256k1_context_preallocated_create(buf, AllPreallocated::FLAGS) },
342 phantom: PhantomData,
343 })
344 }
345}
346
347impl<'buf> Secp256k1<AllPreallocated<'buf>> {
348 pub fn preallocated_new(
350 buf: &'buf mut [AlignedType],
351 ) -> Result<Secp256k1<AllPreallocated<'buf>>, Error> {
352 Secp256k1::preallocated_gen_new(buf)
353 }
354 pub fn preallocate_size() -> usize { Self::preallocate_size_gen() }
356
357 pub unsafe fn from_raw_all(
377 raw_ctx: NonNull<ffi::Context>,
378 ) -> ManuallyDrop<Secp256k1<AllPreallocated<'buf>>> {
379 ManuallyDrop::new(Secp256k1 { ctx: raw_ctx, phantom: PhantomData })
380 }
381}
382
383impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
384 pub fn preallocated_signing_only(
386 buf: &'buf mut [AlignedType],
387 ) -> Result<Secp256k1<SignOnlyPreallocated<'buf>>, Error> {
388 Secp256k1::preallocated_gen_new(buf)
389 }
390
391 #[inline]
393 pub fn preallocate_signing_size() -> usize { Self::preallocate_size_gen() }
394
395 pub unsafe fn from_raw_signing_only(
401 raw_ctx: NonNull<ffi::Context>,
402 ) -> ManuallyDrop<Secp256k1<SignOnlyPreallocated<'buf>>> {
403 ManuallyDrop::new(Secp256k1 { ctx: raw_ctx, phantom: PhantomData })
404 }
405}
406
407impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
408 pub fn preallocated_verification_only(
410 buf: &'buf mut [AlignedType],
411 ) -> Result<Secp256k1<VerifyOnlyPreallocated<'buf>>, Error> {
412 Secp256k1::preallocated_gen_new(buf)
413 }
414
415 #[inline]
417 pub fn preallocate_verification_size() -> usize { Self::preallocate_size_gen() }
418
419 pub unsafe fn from_raw_verification_only(
425 raw_ctx: NonNull<ffi::Context>,
426 ) -> ManuallyDrop<Secp256k1<VerifyOnlyPreallocated<'buf>>> {
427 ManuallyDrop::new(Secp256k1 { ctx: raw_ctx, phantom: PhantomData })
428 }
429}