Skip to content

Commit 75784ec

Browse files
committed
Implemented context create/destroy in rust
1 parent 2a32f8c commit 75784ec

File tree

1 file changed

+47
-3
lines changed

1 file changed

+47
-3
lines changed

src/ffi.rs

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
//! # FFI bindings
1717
//! Direct bindings to the underlying C library functions. These should
1818
//! not be needed for most users.
19-
use core::{mem, hash};
19+
use core::{mem, hash, slice};
2020
use types::*;
2121

2222
/// Flag for context to enable no precomputation
@@ -260,6 +260,50 @@ extern "C" {
260260
}
261261

262262

263+
#[cfg(feature = "std")]
264+
#[no_mangle]
265+
/// A reimplementation of the C function `secp256k1_context_create` in rust.
266+
///
267+
/// This function allocates memory, the pointer should be deallocated using `secp256k1_context_destroy`
268+
/// A failure to do so will result in a memory leak.
269+
///
270+
/// This will create a secp256k1 raw context.
271+
// Returns: a newly created context object.
272+
// In: flags: which parts of the context to initialize.
273+
pub unsafe extern "C" fn secp256k1_context_create(flags: c_uint) -> *mut Context {
274+
assert!(mem::align_of::<usize>() >= mem::align_of::<u8>());
275+
assert_eq!(mem::size_of::<usize>(), mem::size_of::<&usize>());
276+
277+
let word_size = mem::size_of::<usize>();
278+
let n_words = (secp256k1_context_preallocated_size(flags) + word_size - 1) / word_size;
279+
280+
let buf = vec![0usize; n_words + 1].into_boxed_slice();
281+
let ptr = Box::into_raw(buf) as *mut usize;
282+
::core::ptr::write(ptr, n_words);
283+
let ptr: *mut usize = ptr.offset(1);
284+
285+
secp256k1_context_preallocated_create(ptr as *mut c_void, flags)
286+
}
287+
288+
#[cfg(feature = "std")]
289+
#[no_mangle]
290+
/// A reimplementation of the C function `secp256k1_context_destroy` in rust.
291+
///
292+
/// This function destroys and deallcates the context created by `secp256k1_context_create`.
293+
///
294+
/// The pointer shouldn't be used after passing to this function, consider it as passing it to `free()`.
295+
///
296+
pub unsafe extern "C" fn secp256k1_context_destroy(ctx: *mut Context) {
297+
secp256k1_context_preallocated_destroy(ctx);
298+
let ctx: *mut usize = ctx as *mut usize;
299+
300+
let n_words_ptr: *mut usize = ctx.offset(-1);
301+
let n_words: usize = ::core::ptr::read(n_words_ptr);
302+
let slice: &mut [usize] = slice::from_raw_parts_mut(n_words_ptr , n_words+1);
303+
let _ = Box::from_raw(slice as *mut [usize]);
304+
}
305+
306+
263307
#[no_mangle]
264308
/// **This function is an override for the C function, this is the an edited version of the original description:**
265309
///
@@ -280,7 +324,7 @@ extern "C" {
280324
/// See also secp256k1_default_error_callback_fn.
281325
///
282326
pub unsafe extern "C" fn secp256k1_default_illegal_callback_fn(message: *const c_char, _data: *mut c_void) {
283-
use core::{str, slice};
327+
use core::str;
284328
let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message));
285329
let msg = str::from_utf8_unchecked(msg_slice);
286330
panic!("[libsecp256k1] illegal argument. {}", msg);
@@ -302,7 +346,7 @@ pub unsafe extern "C" fn secp256k1_default_illegal_callback_fn(message: *const c
302346
/// See also secp256k1_default_illegal_callback_fn.
303347
///
304348
pub unsafe extern "C" fn secp256k1_default_error_callback_fn(message: *const c_char, _data: *mut c_void) {
305-
use core::{str, slice};
349+
use core::str;
306350
let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message));
307351
let msg = str::from_utf8_unchecked(msg_slice);
308352
panic!("[libsecp256k1] internal consistency check failed {}", msg);

0 commit comments

Comments
 (0)