Skip to content

Commit b732f24

Browse files
authored
Merge pull request #130 from elichai/symbols
Implemented context create/destroy in rust
2 parents 2a32f8c + a4f6b27 commit b732f24

File tree

4 files changed

+84
-4
lines changed

4 files changed

+84
-4
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 0.14.1 - 2019-07-14
2+
3+
* Implemented FFI functions: `secp256k1_context_create` and `secp256k1_context_destroy` in rust.
4+
15
# 0.14.0 - 2019-07-08
26

37
* [Feature-gate endormorphism optimization](https://github.com/rust-bitcoin/rust-secp256k1/pull/120)

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
name = "secp256k1"
4-
version = "0.14.0"
4+
version = "0.14.1"
55
authors = [ "Dawid Ciężarkiewicz <[email protected]>",
66
"Andrew Poelstra <[email protected]>" ]
77
license = "CC0-1.0"

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

src/lib.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,12 +681,15 @@ fn from_hex(hex: &str, target: &mut [u8]) -> Result<usize, ()> {
681681
mod tests {
682682
use rand::{RngCore, thread_rng};
683683
use std::str::FromStr;
684+
use std::marker::PhantomData;
684685

685686
use key::{SecretKey, PublicKey};
686687
use super::from_hex;
687688
use super::constants;
688689
use super::{Secp256k1, Signature, Message};
689690
use super::Error::{InvalidMessage, IncorrectSignature, InvalidSignature};
691+
use ffi;
692+
use context::*;
690693

691694
macro_rules! hex {
692695
($hex:expr) => ({
@@ -696,6 +699,35 @@ mod tests {
696699
});
697700
}
698701

702+
703+
#[test]
704+
fn test_manual_create_destroy() {
705+
let ctx_full = unsafe { ffi::secp256k1_context_create(AllPreallocated::FLAGS) };
706+
let ctx_sign = unsafe { ffi::secp256k1_context_create(SignOnlyPreallocated::FLAGS) };
707+
let ctx_vrfy = unsafe { ffi::secp256k1_context_create(VerifyOnlyPreallocated::FLAGS) };
708+
709+
let buf: *mut [u8] = &mut [0u8;0] as _;
710+
let full: Secp256k1<AllPreallocated> = Secp256k1{ctx: ctx_full, phantom: PhantomData, buf};
711+
let sign: Secp256k1<SignOnlyPreallocated> = Secp256k1{ctx: ctx_sign, phantom: PhantomData, buf};
712+
let vrfy: Secp256k1<VerifyOnlyPreallocated> = Secp256k1{ctx: ctx_vrfy, phantom: PhantomData, buf};
713+
714+
let (sk, pk) = full.generate_keypair(&mut thread_rng());
715+
let msg = Message::from_slice(&[2u8; 32]).unwrap();
716+
// Try signing
717+
assert_eq!(sign.sign(&msg, &sk), full.sign(&msg, &sk));
718+
let sig = full.sign(&msg, &sk);
719+
720+
// Try verifying
721+
assert!(vrfy.verify(&msg, &sig, &pk).is_ok());
722+
assert!(full.verify(&msg, &sig, &pk).is_ok());
723+
724+
drop(full);drop(sign);drop(vrfy);
725+
726+
unsafe { ffi::secp256k1_context_destroy(ctx_vrfy) };
727+
unsafe { ffi::secp256k1_context_destroy(ctx_sign) };
728+
unsafe { ffi::secp256k1_context_destroy(ctx_full) };
729+
}
730+
699731
#[test]
700732
fn test_preallocation() {
701733
let mut buf_ful = vec![0u8; Secp256k1::preallocate_size()];

0 commit comments

Comments
 (0)