use crate::KeyAggContext;
use std::error::Error;
use std::fmt;
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
pub struct KeyAggError;
impl fmt::Display for KeyAggError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("computed an invalid aggregated key from a collection of public keys")
}
}
impl Error for KeyAggError {}
impl From<secp::errors::InfinityPointError> for KeyAggError {
fn from(_: secp::errors::InfinityPointError) -> Self {
KeyAggError
}
}
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
pub struct InvalidSecretKeysError;
impl fmt::Display for InvalidSecretKeysError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("missing or invalid secret keys provided for aggregation")
}
}
impl Error for InvalidSecretKeysError {}
impl From<secp::errors::ZeroScalarError> for InvalidSecretKeysError {
fn from(_: secp::errors::ZeroScalarError) -> Self {
InvalidSecretKeysError
}
}
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
pub struct TweakError;
impl fmt::Display for TweakError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("tweak value is invalid")
}
}
impl Error for TweakError {}
impl From<secp::errors::InfinityPointError> for TweakError {
fn from(_: secp::errors::InfinityPointError) -> Self {
TweakError
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum RoundSetupError {
InvalidSignerIndex {
index: usize,
n_signers: usize,
},
MismatchingSecretKey,
}
impl RoundSetupError {
pub(crate) fn signer_index(index: usize, n_signers: usize) -> Self {
Self::InvalidSignerIndex { index, n_signers }
}
}
impl fmt::Display for RoundSetupError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
RoundSetupError::InvalidSignerIndex { index, n_signers } => write!(
f,
"signer index {} is out of range for group of {} signers",
index, n_signers
),
RoundSetupError::MismatchingSecretKey => write!(
f,
"secret key given in SecNonceSpices does not correspond to the requested signer_index"
),
}
}
}
impl Error for RoundSetupError {}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SigningError {
UnknownKey,
SecNoncePubkeyMismatch,
SelfVerifyFail,
}
impl fmt::Display for SigningError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"failed to create signature: {}",
match self {
Self::UnknownKey => "signing key is not a member of the group",
Self::SecNoncePubkeyMismatch =>
"secret nonce public key does not match signing key",
Self::SelfVerifyFail => "failed to verify our own signature; something is wrong",
}
)
}
}
impl Error for SigningError {}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum VerifyError {
UnknownKey,
BadSignature,
}
impl fmt::Display for VerifyError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"failed to verify signature: {}",
match self {
Self::UnknownKey => "public key is not a member of the group",
Self::BadSignature => "signature is invalid",
}
)
}
}
impl Error for VerifyError {}
impl From<VerifyError> for SigningError {
fn from(_: VerifyError) -> Self {
SigningError::SelfVerifyFail
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ContributionFaultReason {
OutOfRange(usize),
InconsistentContribution,
InvalidSignature,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct RoundContributionError {
pub index: usize,
pub reason: ContributionFaultReason,
}
impl RoundContributionError {
pub fn out_of_range(index: usize, n_signers: usize) -> RoundContributionError {
RoundContributionError {
index,
reason: ContributionFaultReason::OutOfRange(n_signers),
}
}
pub fn inconsistent_contribution(index: usize) -> RoundContributionError {
RoundContributionError {
index,
reason: ContributionFaultReason::InconsistentContribution,
}
}
pub fn invalid_signature(index: usize) -> RoundContributionError {
RoundContributionError {
index,
reason: ContributionFaultReason::InvalidSignature,
}
}
}
impl fmt::Display for RoundContributionError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use ContributionFaultReason::*;
write!(
f,
"invalid signer index {}: {}",
self.index,
match self.reason {
OutOfRange(n_signers) => format!("exceeds max index for {} signers", n_signers),
InconsistentContribution =>
"received inconsistent contributions from same signer".to_string(),
InvalidSignature => "received invalid partial signature from peer".to_string(),
}
)
}
}
impl Error for RoundContributionError {}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum RoundFinalizeError {
Incomplete,
SigningError(SigningError),
InvalidAggregatedSignature(VerifyError),
}
impl fmt::Display for RoundFinalizeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"cannot finalize round: {}",
match self {
Self::Incomplete => "not all signers have contributed".to_string(),
Self::SigningError(e) => format!("signing failed, {}", e),
Self::InvalidAggregatedSignature(e) =>
format!("could not verify aggregated signature: {}", e),
}
)
}
}
impl Error for RoundFinalizeError {}
impl From<SigningError> for RoundFinalizeError {
fn from(e: SigningError) -> Self {
RoundFinalizeError::SigningError(e)
}
}
impl From<VerifyError> for RoundFinalizeError {
fn from(e: VerifyError) -> Self {
RoundFinalizeError::InvalidAggregatedSignature(e)
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum DecodeFailureReason {
BadHexFormat(base16ct::Error),
BadLength(usize),
InvalidPoint,
InvalidScalar,
Custom(String),
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct DecodeError<T> {
pub reason: DecodeFailureReason,
phantom: std::marker::PhantomData<T>,
}
impl<T> DecodeError<T> {
pub fn new(reason: DecodeFailureReason) -> Self {
DecodeError {
reason,
phantom: std::marker::PhantomData,
}
}
pub fn bad_length(size: usize) -> Self {
let reason = DecodeFailureReason::BadLength(size);
DecodeError::new(reason)
}
pub fn custom(s: impl fmt::Display) -> Self {
let reason = DecodeFailureReason::Custom(s.to_string());
DecodeError::new(reason)
}
pub fn convert<U>(self) -> DecodeError<U> {
DecodeError::new(self.reason)
}
}
impl<T> fmt::Display for DecodeError<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use DecodeFailureReason::*;
write!(
f,
"error decoding {}: {}",
std::any::type_name::<T>(),
match &self.reason {
BadHexFormat(e) => format!("hex decoding error: {}", e),
BadLength(size) => format!("unexpected length {}", size),
InvalidPoint => secp::errors::InvalidPointBytes.to_string(),
InvalidScalar => secp::errors::InvalidScalarBytes.to_string(),
Custom(s) => s.to_string(),
}
)
}
}
impl<T: fmt::Debug> std::error::Error for DecodeError<T> {}
impl<T> From<secp::errors::InvalidPointBytes> for DecodeError<T> {
fn from(_: secp::errors::InvalidPointBytes) -> Self {
DecodeError::new(DecodeFailureReason::InvalidPoint)
}
}
impl<T> From<secp::errors::InvalidScalarBytes> for DecodeError<T> {
fn from(_: secp::errors::InvalidScalarBytes) -> Self {
DecodeError::new(DecodeFailureReason::InvalidScalar)
}
}
impl<T> From<base16ct::Error> for DecodeError<T> {
fn from(e: base16ct::Error) -> Self {
DecodeError::new(DecodeFailureReason::BadHexFormat(e))
}
}
impl From<KeyAggError> for DecodeError<KeyAggContext> {
fn from(e: KeyAggError) -> Self {
DecodeError::custom(e)
}
}
impl From<TweakError> for DecodeError<KeyAggContext> {
fn from(_: TweakError) -> Self {
DecodeError::custom("serialized KeyAggContext contains an invalid tweak")
}
}