Skip to content

Commit 571c8eb

Browse files
committed
Implementing the pre allocated context
1 parent 3e4b1e7 commit 571c8eb

File tree

1 file changed

+99
-27
lines changed

1 file changed

+99
-27
lines changed

src/lib.rs

+99-27
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ pub use key::SecretKey;
159159
pub use key::PublicKey;
160160
use core::marker::PhantomData;
161161
use core::ops::Deref;
162+
use self::types::c_uint;
163+
use types::c_void;
162164

163165
/// An ECDSA signature
164166
#[derive(Copy, Clone, PartialEq, Eq)]
@@ -463,6 +465,8 @@ pub enum Error {
463465
InvalidRecoveryId,
464466
/// Invalid tweak for add_*_assign or mul_*_assign
465467
InvalidTweak,
468+
/// Didn't pass enough memory to `new_preallocated_internal`
469+
NotEnoughMemory,
466470
}
467471

468472
impl Error {
@@ -475,6 +479,7 @@ impl Error {
475479
Error::InvalidSecretKey => "secp: malformed or out-of-range secret key",
476480
Error::InvalidRecoveryId => "secp: bad recovery id",
477481
Error::InvalidTweak => "secp: bad tweak",
482+
Error::NotEnoughMemory => "secp: not enough memory allocated",
478483
}
479484
}
480485
}
@@ -513,26 +518,29 @@ impl Verification for VerifyOnly {}
513518
impl Verification for All {}
514519

515520
/// The secp256k1 engine, used to execute all signature operations
516-
pub struct Secp256k1<C> {
521+
pub struct Secp256k1<'buf, C> {
517522
ctx: *mut ffi::Context,
518-
phantom: PhantomData<C>
523+
phantom: PhantomData<C>,
524+
_buf: Option<&'buf [u8]>,
519525
}
520526

521527
// The underlying secp context does not contain any references to memory it does not own
522-
unsafe impl<C> Send for Secp256k1<C> {}
528+
unsafe impl<'buf, C> Send for Secp256k1<'buf, C> {}
523529
// The API does not permit any mutation of `Secp256k1` objects except through `&mut` references
524-
unsafe impl<C> Sync for Secp256k1<C> {}
530+
unsafe impl<'buf, C> Sync for Secp256k1<'buf, C> {}
525531

526-
impl<C> Clone for Secp256k1<C> {
527-
fn clone(&self) -> Secp256k1<C> {
532+
#[cfg(feature = "std")]
533+
impl<'buf, C> Clone for Secp256k1<'buf, C> {
534+
fn clone(&self) -> Secp256k1<'static, C> {
528535
Secp256k1 {
529536
ctx: unsafe { ffi::secp256k1_context_clone(self.ctx) },
530-
phantom: self.phantom
537+
phantom: self.phantom,
538+
_buf: None,
531539
}
532540
}
533541
}
534542

535-
impl<C> PartialEq for Secp256k1<C> {
543+
impl<'buf, C> PartialEq for Secp256k1<'buf, C> {
536544
fn eq(&self, _other: &Secp256k1<C>) -> bool { true }
537545
}
538546

@@ -566,60 +574,90 @@ impl Deref for SerializedSignature {
566574

567575
impl Eq for SerializedSignature {}
568576

569-
impl<C> Eq for Secp256k1<C> { }
577+
impl<'buf, C> Eq for Secp256k1<'buf, C> { }
570578

571-
impl<C> Drop for Secp256k1<C> {
579+
impl<'buf, C> Drop for Secp256k1<'buf, C> {
572580
fn drop(&mut self) {
573-
unsafe { ffi::secp256k1_context_destroy(self.ctx); }
581+
match self._buf {
582+
None => unsafe { ffi::secp256k1_context_destroy(self.ctx) },
583+
Some(_) => unsafe { ffi::secp256k1_context_preallocated_destroy(self.ctx) },
584+
}
574585
}
575586
}
576587

577-
impl fmt::Debug for Secp256k1<SignOnly> {
588+
impl<'buf> fmt::Debug for Secp256k1<'buf, SignOnly> {
578589
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
579590
write!(f, "<secp256k1 context {:?}, signing only>", self.ctx)
580591
}
581592
}
582593

583-
impl fmt::Debug for Secp256k1<VerifyOnly> {
594+
impl<'buf> fmt::Debug for Secp256k1<'buf, VerifyOnly> {
584595
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
585596
write!(f, "<secp256k1 context {:?}, verification only>", self.ctx)
586597
}
587598
}
588599

589-
impl fmt::Debug for Secp256k1<All> {
600+
impl<'buf> fmt::Debug for Secp256k1<'buf, All> {
590601
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
591602
write!(f, "<secp256k1 context {:?}, all capabilities>", self.ctx)
592603
}
593604
}
594605

595-
impl Secp256k1<All> {
606+
impl<'buf> Secp256k1<'buf, All> {
607+
const FLAGS: c_uint = ffi::SECP256K1_START_SIGN | ffi::SECP256K1_START_VERIFY;
596608
/// Creates a new Secp256k1 context with all capabilities
597-
pub fn new() -> Secp256k1<All> {
598-
Secp256k1 { ctx: unsafe { ffi::secp256k1_context_create(ffi::SECP256K1_START_SIGN | ffi::SECP256K1_START_VERIFY) }, phantom: PhantomData }
609+
pub fn new() -> Secp256k1<'buf, All> {
610+
Secp256k1 { ctx: unsafe { ffi::secp256k1_context_create(Self::FLAGS) }, phantom: PhantomData, _buf: None }
611+
}
612+
613+
pub fn get_preallocated_size() -> usize {
614+
Self::get_preallocated_size_internal(Self::FLAGS)
615+
}
616+
617+
pub fn new_preallocated(buf: &'buf mut [u8]) -> Result<Secp256k1<'buf, All>, Error> {
618+
Self::new_preallocated_internal(buf, Self::FLAGS)
599619
}
600620
}
601621

602-
impl Default for Secp256k1<All> {
622+
impl<'buf> Default for Secp256k1<'buf, All> {
603623
fn default() -> Self {
604624
Self::new()
605625
}
606626
}
607627

608-
impl Secp256k1<SignOnly> {
628+
impl<'buf> Secp256k1<'buf, SignOnly> {
629+
const FLAGS: c_uint = ffi::SECP256K1_START_SIGN;
609630
/// Creates a new Secp256k1 context that can only be used for signing
610-
pub fn signing_only() -> Secp256k1<SignOnly> {
611-
Secp256k1 { ctx: unsafe { ffi::secp256k1_context_create(ffi::SECP256K1_START_SIGN) }, phantom: PhantomData }
631+
pub fn signing_only() -> Secp256k1<'buf, SignOnly> {
632+
Secp256k1 { ctx: unsafe { ffi::secp256k1_context_create(Self::FLAGS) }, phantom: PhantomData, _buf: None }
633+
}
634+
635+
pub fn get_preallocated_signing_only_size() -> usize {
636+
Self::get_preallocated_size_internal(Self::FLAGS)
637+
}
638+
639+
pub fn new_preallocated_signing_only(buf: &'buf mut [u8]) -> Result<Secp256k1<'buf, SignOnly>, Error>{
640+
Self::new_preallocated_internal(buf, Self::FLAGS)
612641
}
613642
}
614643

615-
impl Secp256k1<VerifyOnly> {
644+
impl<'buf> Secp256k1<'buf, VerifyOnly> {
645+
const FLAGS: c_uint = ffi::SECP256K1_START_VERIFY;
616646
/// Creates a new Secp256k1 context that can only be used for verification
617-
pub fn verification_only() -> Secp256k1<VerifyOnly> {
618-
Secp256k1 { ctx: unsafe { ffi::secp256k1_context_create(ffi::SECP256K1_START_VERIFY) }, phantom: PhantomData }
647+
pub fn verification_only() -> Secp256k1<'buf, VerifyOnly> {
648+
Secp256k1 { ctx: unsafe { ffi::secp256k1_context_create(Self::FLAGS) }, phantom: PhantomData, _buf: None }
649+
}
650+
651+
pub fn get_preallocated_verification_only_size() -> usize {
652+
Self::get_preallocated_size_internal(Self::FLAGS)
653+
}
654+
655+
pub fn new_preallocated_verification_only(buf: &'buf mut [u8]) -> Result<Secp256k1<'buf, VerifyOnly>, Error>{
656+
Self::new_preallocated_internal(buf, Self::FLAGS)
619657
}
620658
}
621659

622-
impl<C> Secp256k1<C> {
660+
impl<'buf, C> Secp256k1<'buf, C> {
623661

624662
/// Getter for the raw pointer to the underlying secp256k1 context. This
625663
/// shouldn't be needed with normal usage of the library. It enables
@@ -650,9 +688,25 @@ impl<C> Secp256k1<C> {
650688
}
651689
}
652690

691+
pub(crate) fn get_preallocated_size_internal(flags: c_uint) -> usize {
692+
unsafe { ffi::secp256k1_context_preallocated_size(flags) }
693+
}
694+
695+
pub(crate) fn new_preallocated_internal(buf: &'buf mut [u8], flags: c_uint) -> Result<Secp256k1<'buf, C>, Error> {
696+
if buf.len() < Self::get_preallocated_size_internal(flags) {
697+
return Err(Error::NotEnoughMemory);
698+
}
699+
700+
Ok(Secp256k1 {
701+
ctx: unsafe { ffi::secp256k1_context_preallocated_create(buf.as_mut_ptr() as *mut c_void, flags) },
702+
phantom: PhantomData,
703+
_buf: Some(buf)
704+
})
705+
}
706+
653707
}
654708

655-
impl<C: Signing> Secp256k1<C> {
709+
impl<'buf, C: Signing> Secp256k1<'buf, C> {
656710

657711
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
658712
/// Requires a signing-capable context.
@@ -685,7 +739,7 @@ impl<C: Signing> Secp256k1<C> {
685739
}
686740
}
687741

688-
impl<C: Verification> Secp256k1<C> {
742+
impl<'buf, C: Verification> Secp256k1<'buf, C> {
689743
/// Checks that `sig` is a valid ECDSA signature for `msg` using the public
690744
/// key `pubkey`. Returns `Ok(true)` on success. Note that this function cannot
691745
/// be used for Bitcoin consensus checking since there may exist signatures
@@ -741,6 +795,7 @@ mod tests {
741795
use super::constants;
742796
use super::{Secp256k1, Signature, Message};
743797
use super::Error::{InvalidMessage, IncorrectSignature, InvalidSignature};
798+
use ::{SignOnly, VerifyOnly, All};
744799

745800
macro_rules! hex {
746801
($hex:expr) => ({
@@ -756,6 +811,23 @@ mod tests {
756811
let vrfy = Secp256k1::verification_only();
757812
let full = Secp256k1::new();
758813

814+
capabilities_internal(sign, vrfy, full);
815+
816+
}
817+
818+
#[test]
819+
fn preallocated_capabilities() {
820+
let mut sign_buf = vec![0u8; Secp256k1::get_preallocated_signing_only_size()];
821+
let mut verify_buf = vec![0u8; Secp256k1::get_preallocated_verification_only_size()];
822+
let mut all_buf = vec![0u8; Secp256k1::get_preallocated_size()];
823+
let sign: Secp256k1<SignOnly> = Secp256k1::new_preallocated_signing_only(&mut sign_buf).unwrap();
824+
let vrfy: Secp256k1<VerifyOnly> = Secp256k1::new_preallocated_verification_only(&mut verify_buf).unwrap();
825+
let full: Secp256k1<All> = Secp256k1::new_preallocated(&mut all_buf).unwrap();
826+
827+
capabilities_internal(sign, vrfy, full);
828+
}
829+
830+
fn capabilities_internal(sign: Secp256k1<SignOnly>, vrfy: Secp256k1<VerifyOnly>, full: Secp256k1<All>) {
759831
let mut msg = [0u8; 32];
760832
thread_rng().fill_bytes(&mut msg);
761833
let msg = Message::from_slice(&msg).unwrap();

0 commit comments

Comments
 (0)