Merge pull request #130 from elichai/symbols

Implemented context create/destroy in rust
This commit is contained in:
Andrew Poelstra 2019-07-14 21:26:55 +00:00 committed by GitHub
commit b732f240e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 84 additions and 4 deletions

View File

@ -1,3 +1,7 @@
# 0.14.1 - 2019-07-14
* Implemented FFI functions: `secp256k1_context_create` and `secp256k1_context_destroy` in rust.
# 0.14.0 - 2019-07-08 # 0.14.0 - 2019-07-08
* [Feature-gate endormorphism optimization](https://github.com/rust-bitcoin/rust-secp256k1/pull/120) * [Feature-gate endormorphism optimization](https://github.com/rust-bitcoin/rust-secp256k1/pull/120)

View File

@ -1,7 +1,7 @@
[package] [package]
name = "secp256k1" name = "secp256k1"
version = "0.14.0" version = "0.14.1"
authors = [ "Dawid Ciężarkiewicz <dpc@ucore.info>", authors = [ "Dawid Ciężarkiewicz <dpc@ucore.info>",
"Andrew Poelstra <apoelstra@wpsoftware.net>" ] "Andrew Poelstra <apoelstra@wpsoftware.net>" ]
license = "CC0-1.0" license = "CC0-1.0"

View File

@ -16,7 +16,7 @@
//! # FFI bindings //! # FFI bindings
//! Direct bindings to the underlying C library functions. These should //! Direct bindings to the underlying C library functions. These should
//! not be needed for most users. //! not be needed for most users.
use core::{mem, hash}; use core::{mem, hash, slice};
use types::*; use types::*;
/// Flag for context to enable no precomputation /// Flag for context to enable no precomputation
@ -260,6 +260,50 @@ extern "C" {
} }
#[cfg(feature = "std")]
#[no_mangle]
/// A reimplementation of the C function `secp256k1_context_create` in rust.
///
/// This function allocates memory, the pointer should be deallocated using `secp256k1_context_destroy`
/// A failure to do so will result in a memory leak.
///
/// This will create a secp256k1 raw context.
// Returns: a newly created context object.
// In: flags: which parts of the context to initialize.
pub unsafe extern "C" fn secp256k1_context_create(flags: c_uint) -> *mut Context {
assert!(mem::align_of::<usize>() >= mem::align_of::<u8>());
assert_eq!(mem::size_of::<usize>(), mem::size_of::<&usize>());
let word_size = mem::size_of::<usize>();
let n_words = (secp256k1_context_preallocated_size(flags) + word_size - 1) / word_size;
let buf = vec![0usize; n_words + 1].into_boxed_slice();
let ptr = Box::into_raw(buf) as *mut usize;
::core::ptr::write(ptr, n_words);
let ptr: *mut usize = ptr.offset(1);
secp256k1_context_preallocated_create(ptr as *mut c_void, flags)
}
#[cfg(feature = "std")]
#[no_mangle]
/// A reimplementation of the C function `secp256k1_context_destroy` in rust.
///
/// This function destroys and deallcates the context created by `secp256k1_context_create`.
///
/// The pointer shouldn't be used after passing to this function, consider it as passing it to `free()`.
///
pub unsafe extern "C" fn secp256k1_context_destroy(ctx: *mut Context) {
secp256k1_context_preallocated_destroy(ctx);
let ctx: *mut usize = ctx as *mut usize;
let n_words_ptr: *mut usize = ctx.offset(-1);
let n_words: usize = ::core::ptr::read(n_words_ptr);
let slice: &mut [usize] = slice::from_raw_parts_mut(n_words_ptr , n_words+1);
let _ = Box::from_raw(slice as *mut [usize]);
}
#[no_mangle] #[no_mangle]
/// **This function is an override for the C function, this is the an edited version of the original description:** /// **This function is an override for the C function, this is the an edited version of the original description:**
/// ///
@ -280,7 +324,7 @@ extern "C" {
/// See also secp256k1_default_error_callback_fn. /// See also secp256k1_default_error_callback_fn.
/// ///
pub unsafe extern "C" fn secp256k1_default_illegal_callback_fn(message: *const c_char, _data: *mut c_void) { pub unsafe extern "C" fn secp256k1_default_illegal_callback_fn(message: *const c_char, _data: *mut c_void) {
use core::{str, slice}; use core::str;
let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message)); let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message));
let msg = str::from_utf8_unchecked(msg_slice); let msg = str::from_utf8_unchecked(msg_slice);
panic!("[libsecp256k1] illegal argument. {}", msg); panic!("[libsecp256k1] illegal argument. {}", msg);
@ -302,7 +346,7 @@ pub unsafe extern "C" fn secp256k1_default_illegal_callback_fn(message: *const c
/// See also secp256k1_default_illegal_callback_fn. /// See also secp256k1_default_illegal_callback_fn.
/// ///
pub unsafe extern "C" fn secp256k1_default_error_callback_fn(message: *const c_char, _data: *mut c_void) { pub unsafe extern "C" fn secp256k1_default_error_callback_fn(message: *const c_char, _data: *mut c_void) {
use core::{str, slice}; use core::str;
let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message)); let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message));
let msg = str::from_utf8_unchecked(msg_slice); let msg = str::from_utf8_unchecked(msg_slice);
panic!("[libsecp256k1] internal consistency check failed {}", msg); panic!("[libsecp256k1] internal consistency check failed {}", msg);

View File

@ -681,12 +681,15 @@ fn from_hex(hex: &str, target: &mut [u8]) -> Result<usize, ()> {
mod tests { mod tests {
use rand::{RngCore, thread_rng}; use rand::{RngCore, thread_rng};
use std::str::FromStr; use std::str::FromStr;
use std::marker::PhantomData;
use key::{SecretKey, PublicKey}; use key::{SecretKey, PublicKey};
use super::from_hex; use super::from_hex;
use super::constants; use super::constants;
use super::{Secp256k1, Signature, Message}; use super::{Secp256k1, Signature, Message};
use super::Error::{InvalidMessage, IncorrectSignature, InvalidSignature}; use super::Error::{InvalidMessage, IncorrectSignature, InvalidSignature};
use ffi;
use context::*;
macro_rules! hex { macro_rules! hex {
($hex:expr) => ({ ($hex:expr) => ({
@ -696,6 +699,35 @@ mod tests {
}); });
} }
#[test]
fn test_manual_create_destroy() {
let ctx_full = unsafe { ffi::secp256k1_context_create(AllPreallocated::FLAGS) };
let ctx_sign = unsafe { ffi::secp256k1_context_create(SignOnlyPreallocated::FLAGS) };
let ctx_vrfy = unsafe { ffi::secp256k1_context_create(VerifyOnlyPreallocated::FLAGS) };
let buf: *mut [u8] = &mut [0u8;0] as _;
let full: Secp256k1<AllPreallocated> = Secp256k1{ctx: ctx_full, phantom: PhantomData, buf};
let sign: Secp256k1<SignOnlyPreallocated> = Secp256k1{ctx: ctx_sign, phantom: PhantomData, buf};
let vrfy: Secp256k1<VerifyOnlyPreallocated> = Secp256k1{ctx: ctx_vrfy, phantom: PhantomData, buf};
let (sk, pk) = full.generate_keypair(&mut thread_rng());
let msg = Message::from_slice(&[2u8; 32]).unwrap();
// Try signing
assert_eq!(sign.sign(&msg, &sk), full.sign(&msg, &sk));
let sig = full.sign(&msg, &sk);
// Try verifying
assert!(vrfy.verify(&msg, &sig, &pk).is_ok());
assert!(full.verify(&msg, &sig, &pk).is_ok());
drop(full);drop(sign);drop(vrfy);
unsafe { ffi::secp256k1_context_destroy(ctx_vrfy) };
unsafe { ffi::secp256k1_context_destroy(ctx_sign) };
unsafe { ffi::secp256k1_context_destroy(ctx_full) };
}
#[test] #[test]
fn test_preallocation() { fn test_preallocation() {
let mut buf_ful = vec![0u8; Secp256k1::preallocate_size()]; let mut buf_ful = vec![0u8; Secp256k1::preallocate_size()];