Skip to content

Commit f71b678

Browse files
committed
Split general error into specific
Currently we have a large general error type. Create specific error types for each function as needed so that a function returns ever variant available in its return type.
1 parent ec02f3f commit f71b678

15 files changed

+1028
-309
lines changed

examples/sign_verify_recovery.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ extern crate secp256k1;
44
use hashes::{sha256, Hash};
55
use secp256k1::{ecdsa, Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification};
66

7+
// Notice that we provide a general error type for this crate and conversion
8+
// functions to it from all the other error types so `?` works as expected.
79
fn recover<C: Verification>(
810
secp: &Secp256k1<C>,
911
msg: &[u8],
@@ -15,7 +17,7 @@ fn recover<C: Verification>(
1517
let id = ecdsa::RecoveryId::from_i32(recovery_id as i32)?;
1618
let sig = ecdsa::RecoverableSignature::from_compact(&sig, id)?;
1719

18-
secp.recover_ecdsa(&msg, &sig)
20+
Ok(secp.recover_ecdsa(&msg, &sig)?)
1921
}
2022

2123
fn sign_recovery<C: Signing>(

src/context.rs

+26-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: CC0-1.0
22

3+
use core::fmt;
34
use core::marker::PhantomData;
45
use core::mem::ManuallyDrop;
56
use core::ptr::NonNull;
@@ -8,7 +9,7 @@ use core::ptr::NonNull;
89
pub use self::alloc_only::*;
910
use crate::ffi::types::{c_uint, c_void, AlignedType};
1011
use crate::ffi::{self, CPtr};
11-
use crate::{Error, Secp256k1};
12+
use crate::Secp256k1;
1213

1314
#[cfg(all(feature = "global-context", feature = "std"))]
1415
/// Module implementing a singleton pattern for a global `Secp256k1` context.
@@ -320,14 +321,33 @@ unsafe impl<'buf> PreallocatedContext<'buf> for AllPreallocated<'buf> {}
320321
unsafe impl<'buf> PreallocatedContext<'buf> for SignOnlyPreallocated<'buf> {}
321322
unsafe impl<'buf> PreallocatedContext<'buf> for VerifyOnlyPreallocated<'buf> {}
322323

324+
/// Not enough preallocated memory for the requested buffer size.
325+
#[derive(Debug, Clone, PartialEq, Eq)]
326+
#[non_exhaustive]
327+
#[allow(missing_copy_implementations)] // Don't implement Copy when we use non_exhaustive.
328+
pub struct NotEnoughMemoryError;
329+
330+
impl fmt::Display for NotEnoughMemoryError {
331+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
332+
f.write_str("not enough preallocated memory for the requested buffer size")
333+
}
334+
}
335+
336+
#[cfg(feature = "std")]
337+
impl std::error::Error for NotEnoughMemoryError {
338+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
339+
}
340+
323341
impl<'buf, C: Context + PreallocatedContext<'buf>> Secp256k1<C> {
324342
/// Lets you create a context with a preallocated buffer in a generic manner (sign/verify/all).
325-
pub fn preallocated_gen_new(buf: &'buf mut [AlignedType]) -> Result<Secp256k1<C>, Error> {
343+
pub fn preallocated_gen_new(
344+
buf: &'buf mut [AlignedType],
345+
) -> Result<Secp256k1<C>, NotEnoughMemoryError> {
326346
#[cfg(target_arch = "wasm32")]
327347
ffi::types::sanity_checks_for_wasm();
328348

329349
if buf.len() < Self::preallocate_size_gen() {
330-
return Err(Error::NotEnoughMemory);
350+
return Err(NotEnoughMemoryError);
331351
}
332352
// Safe because buf is not null since it is not empty.
333353
let buf = unsafe { NonNull::new_unchecked(buf.as_mut_c_ptr() as *mut c_void) };
@@ -343,7 +363,7 @@ impl<'buf> Secp256k1<AllPreallocated<'buf>> {
343363
/// Creates a new Secp256k1 context with all capabilities.
344364
pub fn preallocated_new(
345365
buf: &'buf mut [AlignedType],
346-
) -> Result<Secp256k1<AllPreallocated<'buf>>, Error> {
366+
) -> Result<Secp256k1<AllPreallocated<'buf>>, NotEnoughMemoryError> {
347367
Secp256k1::preallocated_gen_new(buf)
348368
}
349369
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for a context.
@@ -378,7 +398,7 @@ impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
378398
/// Creates a new Secp256k1 context that can only be used for signing.
379399
pub fn preallocated_signing_only(
380400
buf: &'buf mut [AlignedType],
381-
) -> Result<Secp256k1<SignOnlyPreallocated<'buf>>, Error> {
401+
) -> Result<Secp256k1<SignOnlyPreallocated<'buf>>, NotEnoughMemoryError> {
382402
Secp256k1::preallocated_gen_new(buf)
383403
}
384404

@@ -402,7 +422,7 @@ impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
402422
/// Creates a new Secp256k1 context that can only be used for verification
403423
pub fn preallocated_verification_only(
404424
buf: &'buf mut [AlignedType],
405-
) -> Result<Secp256k1<VerifyOnlyPreallocated<'buf>>, Error> {
425+
) -> Result<Secp256k1<VerifyOnlyPreallocated<'buf>>, NotEnoughMemoryError> {
406426
Secp256k1::preallocated_gen_new(buf)
407427
}
408428

src/ecdh.rs

+21-6
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
//!
55
66
use core::borrow::Borrow;
7-
use core::{ptr, str};
7+
use core::{fmt, ptr, str};
88

99
use secp256k1_sys::types::{c_int, c_uchar, c_void};
1010

1111
use crate::ffi::{self, CPtr};
1212
use crate::key::{PublicKey, SecretKey};
13-
use crate::{constants, hex, Error};
13+
use crate::{constants, hex};
1414

1515
// The logic for displaying shared secrets relies on this (see `secret.rs`).
1616
const SHARED_SECRET_SIZE: usize = constants::SECRET_KEY_SIZE;
@@ -65,25 +65,25 @@ impl SharedSecret {
6565

6666
/// Creates a shared secret from `bytes` slice.
6767
#[inline]
68-
pub fn from_slice(bytes: &[u8]) -> Result<SharedSecret, Error> {
68+
pub fn from_slice(bytes: &[u8]) -> Result<SharedSecret, SharedSecretError> {
6969
match bytes.len() {
7070
SHARED_SECRET_SIZE => {
7171
let mut ret = [0u8; SHARED_SECRET_SIZE];
7272
ret[..].copy_from_slice(bytes);
7373
Ok(SharedSecret(ret))
7474
}
75-
_ => Err(Error::InvalidSharedSecret),
75+
_ => Err(SharedSecretError),
7676
}
7777
}
7878
}
7979

8080
impl str::FromStr for SharedSecret {
81-
type Err = Error;
81+
type Err = SharedSecretError;
8282
fn from_str(s: &str) -> Result<Self, Self::Err> {
8383
let mut res = [0u8; SHARED_SECRET_SIZE];
8484
match hex::from_hex(s, &mut res) {
8585
Ok(SHARED_SECRET_SIZE) => Ok(SharedSecret::from_bytes(res)),
86-
_ => Err(Error::InvalidSharedSecret),
86+
_ => Err(SharedSecretError),
8787
}
8888
}
8989
}
@@ -183,6 +183,21 @@ impl<'de> ::serde::Deserialize<'de> for SharedSecret {
183183
}
184184
}
185185

186+
/// Share secret is invalid.
187+
#[derive(Debug, Clone, PartialEq, Eq)]
188+
#[non_exhaustive]
189+
#[allow(missing_copy_implementations)] // Don't implement Copy when we use non_exhaustive.
190+
pub struct SharedSecretError;
191+
192+
impl fmt::Display for SharedSecretError {
193+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("shared secret is invalid") }
194+
}
195+
196+
#[cfg(feature = "std")]
197+
impl std::error::Error for SharedSecretError {
198+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
199+
}
200+
186201
#[cfg(test)]
187202
#[allow(unused_imports)]
188203
mod tests {

0 commit comments

Comments
 (0)