@@ -159,6 +159,8 @@ pub use key::SecretKey;
159
159
pub use key:: PublicKey ;
160
160
use core:: marker:: PhantomData ;
161
161
use core:: ops:: Deref ;
162
+ use self :: types:: c_uint;
163
+ use types:: c_void;
162
164
163
165
/// An ECDSA signature
164
166
#[ derive( Copy , Clone , PartialEq , Eq ) ]
@@ -463,6 +465,8 @@ pub enum Error {
463
465
InvalidRecoveryId ,
464
466
/// Invalid tweak for add_*_assign or mul_*_assign
465
467
InvalidTweak ,
468
+ /// Didn't pass enough memory to `new_preallocated_internal`
469
+ NotEnoughMemory ,
466
470
}
467
471
468
472
impl Error {
@@ -475,6 +479,7 @@ impl Error {
475
479
Error :: InvalidSecretKey => "secp: malformed or out-of-range secret key" ,
476
480
Error :: InvalidRecoveryId => "secp: bad recovery id" ,
477
481
Error :: InvalidTweak => "secp: bad tweak" ,
482
+ Error :: NotEnoughMemory => "secp: not enough memory allocated" ,
478
483
}
479
484
}
480
485
}
@@ -513,26 +518,29 @@ impl Verification for VerifyOnly {}
513
518
impl Verification for All { }
514
519
515
520
/// The secp256k1 engine, used to execute all signature operations
516
- pub struct Secp256k1 < C > {
521
+ pub struct Secp256k1 < ' buf , C > {
517
522
ctx : * mut ffi:: Context ,
518
- phantom : PhantomData < C >
523
+ phantom : PhantomData < C > ,
524
+ _buf : Option < & ' buf [ u8 ] > ,
519
525
}
520
526
521
527
// 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 > { }
523
529
// 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 > { }
525
531
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 > {
528
535
Secp256k1 {
529
536
ctx : unsafe { ffi:: secp256k1_context_clone ( self . ctx ) } ,
530
- phantom : self . phantom
537
+ phantom : self . phantom ,
538
+ _buf : None ,
531
539
}
532
540
}
533
541
}
534
542
535
- impl < C > PartialEq for Secp256k1 < C > {
543
+ impl < ' buf , C > PartialEq for Secp256k1 < ' buf , C > {
536
544
fn eq ( & self , _other : & Secp256k1 < C > ) -> bool { true }
537
545
}
538
546
@@ -566,60 +574,90 @@ impl Deref for SerializedSignature {
566
574
567
575
impl Eq for SerializedSignature { }
568
576
569
- impl < C > Eq for Secp256k1 < C > { }
577
+ impl < ' buf , C > Eq for Secp256k1 < ' buf , C > { }
570
578
571
- impl < C > Drop for Secp256k1 < C > {
579
+ impl < ' buf , C > Drop for Secp256k1 < ' buf , C > {
572
580
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
+ }
574
585
}
575
586
}
576
587
577
- impl fmt:: Debug for Secp256k1 < SignOnly > {
588
+ impl < ' buf > fmt:: Debug for Secp256k1 < ' buf , SignOnly > {
578
589
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
579
590
write ! ( f, "<secp256k1 context {:?}, signing only>" , self . ctx)
580
591
}
581
592
}
582
593
583
- impl fmt:: Debug for Secp256k1 < VerifyOnly > {
594
+ impl < ' buf > fmt:: Debug for Secp256k1 < ' buf , VerifyOnly > {
584
595
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
585
596
write ! ( f, "<secp256k1 context {:?}, verification only>" , self . ctx)
586
597
}
587
598
}
588
599
589
- impl fmt:: Debug for Secp256k1 < All > {
600
+ impl < ' buf > fmt:: Debug for Secp256k1 < ' buf , All > {
590
601
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
591
602
write ! ( f, "<secp256k1 context {:?}, all capabilities>" , self . ctx)
592
603
}
593
604
}
594
605
595
- impl Secp256k1 < All > {
606
+ impl < ' buf > Secp256k1 < ' buf , All > {
607
+ const FLAGS : c_uint = ffi:: SECP256K1_START_SIGN | ffi:: SECP256K1_START_VERIFY ;
596
608
/// 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 )
599
619
}
600
620
}
601
621
602
- impl Default for Secp256k1 < All > {
622
+ impl < ' buf > Default for Secp256k1 < ' buf , All > {
603
623
fn default ( ) -> Self {
604
624
Self :: new ( )
605
625
}
606
626
}
607
627
608
- impl Secp256k1 < SignOnly > {
628
+ impl < ' buf > Secp256k1 < ' buf , SignOnly > {
629
+ const FLAGS : c_uint = ffi:: SECP256K1_START_SIGN ;
609
630
/// 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 )
612
641
}
613
642
}
614
643
615
- impl Secp256k1 < VerifyOnly > {
644
+ impl < ' buf > Secp256k1 < ' buf , VerifyOnly > {
645
+ const FLAGS : c_uint = ffi:: SECP256K1_START_VERIFY ;
616
646
/// 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 )
619
657
}
620
658
}
621
659
622
- impl < C > Secp256k1 < C > {
660
+ impl < ' buf , C > Secp256k1 < ' buf , C > {
623
661
624
662
/// Getter for the raw pointer to the underlying secp256k1 context. This
625
663
/// shouldn't be needed with normal usage of the library. It enables
@@ -650,9 +688,25 @@ impl<C> Secp256k1<C> {
650
688
}
651
689
}
652
690
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
+
653
707
}
654
708
655
- impl < C : Signing > Secp256k1 < C > {
709
+ impl < ' buf , C : Signing > Secp256k1 < ' buf , C > {
656
710
657
711
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
658
712
/// Requires a signing-capable context.
@@ -685,7 +739,7 @@ impl<C: Signing> Secp256k1<C> {
685
739
}
686
740
}
687
741
688
- impl < C : Verification > Secp256k1 < C > {
742
+ impl < ' buf , C : Verification > Secp256k1 < ' buf , C > {
689
743
/// Checks that `sig` is a valid ECDSA signature for `msg` using the public
690
744
/// key `pubkey`. Returns `Ok(true)` on success. Note that this function cannot
691
745
/// be used for Bitcoin consensus checking since there may exist signatures
@@ -741,6 +795,7 @@ mod tests {
741
795
use super :: constants;
742
796
use super :: { Secp256k1 , Signature , Message } ;
743
797
use super :: Error :: { InvalidMessage , IncorrectSignature , InvalidSignature } ;
798
+ use :: { SignOnly , VerifyOnly , All } ;
744
799
745
800
macro_rules! hex {
746
801
( $hex: expr) => ( {
@@ -756,6 +811,23 @@ mod tests {
756
811
let vrfy = Secp256k1 :: verification_only ( ) ;
757
812
let full = Secp256k1 :: new ( ) ;
758
813
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 > ) {
759
831
let mut msg = [ 0u8 ; 32 ] ;
760
832
thread_rng ( ) . fill_bytes ( & mut msg) ;
761
833
let msg = Message :: from_slice ( & msg) . unwrap ( ) ;
0 commit comments