cashweb_secp256k1/
context.rs1use core::marker::PhantomData;
2use core::mem::{self, ManuallyDrop};
3use ffi::types::{c_uint, c_void};
4use ffi::{self, types::AlignedType, CPtr};
5use Error;
6use Secp256k1;
7
8#[cfg(feature = "std")]
9pub use self::std_only::*;
10
11#[cfg(feature = "global-context")]
12pub mod global {
14 use rand;
15 use std::ops::Deref;
16 use std::sync::Once;
17 use {All, Secp256k1};
18
19 pub struct GlobalContext {
21 __private: (),
22 }
23
24 pub static SECP256K1: &GlobalContext = &GlobalContext { __private: () };
26
27 impl Deref for GlobalContext {
28 type Target = Secp256k1<All>;
29
30 fn deref(&self) -> &Self::Target {
31 static ONCE: Once = Once::new();
32 static mut CONTEXT: Option<Secp256k1<All>> = None;
33 ONCE.call_once(|| unsafe {
34 let mut ctx = Secp256k1::new();
35 ctx.randomize(&mut rand::thread_rng());
36 CONTEXT = Some(ctx);
37 });
38 unsafe { CONTEXT.as_ref().unwrap() }
39 }
40 }
41}
42
43pub unsafe trait Context: private::Sealed {
46 const FLAGS: c_uint;
48 const DESCRIPTION: &'static str;
50 unsafe fn deallocate(ptr: *mut u8, size: usize);
52}
53
54pub trait Signing: Context {}
56
57pub trait Verification: Context {}
59
60pub struct SignOnlyPreallocated<'buf> {
62 phantom: PhantomData<&'buf ()>,
63}
64
65pub struct VerifyOnlyPreallocated<'buf> {
67 phantom: PhantomData<&'buf ()>,
68}
69
70pub struct AllPreallocated<'buf> {
72 phantom: PhantomData<&'buf ()>,
73}
74
75mod private {
76 use super::*;
77 pub trait Sealed {}
81
82 impl<'buf> Sealed for AllPreallocated<'buf> {}
83 impl<'buf> Sealed for VerifyOnlyPreallocated<'buf> {}
84 impl<'buf> Sealed for SignOnlyPreallocated<'buf> {}
85}
86
87#[cfg(feature = "std")]
88mod std_only {
89 impl private::Sealed for SignOnly {}
90 impl private::Sealed for All {}
91 impl private::Sealed for VerifyOnly {}
92
93 use super::*;
94 use std::alloc;
95 const ALIGN_TO: usize = mem::align_of::<AlignedType>();
96
97 pub enum SignOnly {}
99
100 pub enum VerifyOnly {}
102
103 pub enum All {}
105
106 impl Signing for SignOnly {}
107 impl Signing for All {}
108
109 impl Verification for VerifyOnly {}
110 impl Verification for All {}
111
112 unsafe impl Context for SignOnly {
113 const FLAGS: c_uint = ffi::SECP256K1_START_SIGN;
114 const DESCRIPTION: &'static str = "signing only";
115
116 unsafe fn deallocate(ptr: *mut u8, size: usize) {
117 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
118 alloc::dealloc(ptr, layout);
119 }
120 }
121
122 unsafe impl Context for VerifyOnly {
123 const FLAGS: c_uint = ffi::SECP256K1_START_VERIFY;
124 const DESCRIPTION: &'static str = "verification only";
125
126 unsafe fn deallocate(ptr: *mut u8, size: usize) {
127 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
128 alloc::dealloc(ptr, layout);
129 }
130 }
131
132 unsafe impl Context for All {
133 const FLAGS: c_uint = VerifyOnly::FLAGS | SignOnly::FLAGS;
134 const DESCRIPTION: &'static str = "all capabilities";
135
136 unsafe fn deallocate(ptr: *mut u8, size: usize) {
137 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
138 alloc::dealloc(ptr, layout);
139 }
140 }
141
142 impl<C: Context> Secp256k1<C> {
143 pub fn gen_new() -> Secp256k1<C> {
145 #[cfg(target_arch = "wasm32")]
146 ffi::types::sanity_checks_for_wasm();
147
148 let size = unsafe { ffi::secp256k1_context_preallocated_size(C::FLAGS) };
149 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
150 let ptr = unsafe { alloc::alloc(layout) };
151 Secp256k1 {
152 ctx: unsafe {
153 ffi::secp256k1_context_preallocated_create(ptr as *mut c_void, C::FLAGS)
154 },
155 phantom: PhantomData,
156 size,
157 }
158 }
159 }
160
161 impl Secp256k1<All> {
162 pub fn new() -> Secp256k1<All> {
164 Secp256k1::gen_new()
165 }
166 }
167
168 impl Secp256k1<SignOnly> {
169 pub fn signing_only() -> Secp256k1<SignOnly> {
171 Secp256k1::gen_new()
172 }
173 }
174
175 impl Secp256k1<VerifyOnly> {
176 pub fn verification_only() -> Secp256k1<VerifyOnly> {
178 Secp256k1::gen_new()
179 }
180 }
181
182 impl Default for Secp256k1<All> {
183 fn default() -> Self {
184 Self::new()
185 }
186 }
187
188 impl<C: Context> Clone for Secp256k1<C> {
189 fn clone(&self) -> Secp256k1<C> {
190 let size = unsafe { ffi::secp256k1_context_preallocated_clone_size(self.ctx as _) };
191 let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
192 let ptr = unsafe { alloc::alloc(layout) };
193 Secp256k1 {
194 ctx: unsafe {
195 ffi::secp256k1_context_preallocated_clone(self.ctx, ptr as *mut c_void)
196 },
197 phantom: PhantomData,
198 size,
199 }
200 }
201 }
202}
203
204impl<'buf> Signing for SignOnlyPreallocated<'buf> {}
205impl<'buf> Signing for AllPreallocated<'buf> {}
206
207impl<'buf> Verification for VerifyOnlyPreallocated<'buf> {}
208impl<'buf> Verification for AllPreallocated<'buf> {}
209
210unsafe impl<'buf> Context for SignOnlyPreallocated<'buf> {
211 const FLAGS: c_uint = ffi::SECP256K1_START_SIGN;
212 const DESCRIPTION: &'static str = "signing only";
213
214 unsafe fn deallocate(_ptr: *mut u8, _size: usize) {
215 }
217}
218
219unsafe impl<'buf> Context for VerifyOnlyPreallocated<'buf> {
220 const FLAGS: c_uint = ffi::SECP256K1_START_VERIFY;
221 const DESCRIPTION: &'static str = "verification only";
222
223 unsafe fn deallocate(_ptr: *mut u8, _size: usize) {
224 }
226}
227
228unsafe impl<'buf> Context for AllPreallocated<'buf> {
229 const FLAGS: c_uint = SignOnlyPreallocated::FLAGS | VerifyOnlyPreallocated::FLAGS;
230 const DESCRIPTION: &'static str = "all capabilities";
231
232 unsafe fn deallocate(_ptr: *mut u8, _size: usize) {
233 }
235}
236
237impl<'buf, C: Context + 'buf> Secp256k1<C> {
238 pub fn preallocated_gen_new(buf: &'buf mut [AlignedType]) -> Result<Secp256k1<C>, Error> {
240 #[cfg(target_arch = "wasm32")]
241 ffi::types::sanity_checks_for_wasm();
242
243 if buf.len() < Self::preallocate_size_gen() {
244 return Err(Error::NotEnoughMemory);
245 }
246 Ok(Secp256k1 {
247 ctx: unsafe {
248 ffi::secp256k1_context_preallocated_create(
249 buf.as_mut_c_ptr() as *mut c_void,
250 C::FLAGS,
251 )
252 },
253 phantom: PhantomData,
254 size: 0, })
256 }
257}
258
259impl<'buf> Secp256k1<AllPreallocated<'buf>> {
260 pub fn preallocated_new(
262 buf: &'buf mut [AlignedType],
263 ) -> Result<Secp256k1<AllPreallocated<'buf>>, Error> {
264 Secp256k1::preallocated_gen_new(buf)
265 }
266 pub fn preallocate_size() -> usize {
268 Self::preallocate_size_gen()
269 }
270
271 pub unsafe fn from_raw_all(
283 raw_ctx: *mut ffi::Context,
284 ) -> ManuallyDrop<Secp256k1<AllPreallocated<'buf>>> {
285 ManuallyDrop::new(Secp256k1 {
286 ctx: raw_ctx,
287 phantom: PhantomData,
288 size: 0, })
290 }
291}
292
293impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
294 pub fn preallocated_signing_only(
296 buf: &'buf mut [AlignedType],
297 ) -> Result<Secp256k1<SignOnlyPreallocated<'buf>>, Error> {
298 Secp256k1::preallocated_gen_new(buf)
299 }
300
301 #[inline]
303 pub fn preallocate_signing_size() -> usize {
304 Self::preallocate_size_gen()
305 }
306
307 pub unsafe fn from_raw_signining_only(
319 raw_ctx: *mut ffi::Context,
320 ) -> ManuallyDrop<Secp256k1<SignOnlyPreallocated<'buf>>> {
321 ManuallyDrop::new(Secp256k1 {
322 ctx: raw_ctx,
323 phantom: PhantomData,
324 size: 0, })
326 }
327}
328
329impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
330 pub fn preallocated_verification_only(
332 buf: &'buf mut [AlignedType],
333 ) -> Result<Secp256k1<VerifyOnlyPreallocated<'buf>>, Error> {
334 Secp256k1::preallocated_gen_new(buf)
335 }
336
337 #[inline]
339 pub fn preallocate_verification_size() -> usize {
340 Self::preallocate_size_gen()
341 }
342
343 pub unsafe fn from_raw_verification_only(
355 raw_ctx: *mut ffi::Context,
356 ) -> ManuallyDrop<Secp256k1<VerifyOnlyPreallocated<'buf>>> {
357 ManuallyDrop::new(Secp256k1 {
358 ctx: raw_ctx,
359 phantom: PhantomData,
360 size: 0, })
362 }
363}