Implement Arbitrary for signature types
This commit is contained in:
parent
be4dffbb5b
commit
74a992a5c4
|
@ -7,6 +7,8 @@
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
use core::{fmt, iter};
|
use core::{fmt, iter};
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
use arbitrary::{Arbitrary, Unstructured};
|
||||||
use hex::FromHex;
|
use hex::FromHex;
|
||||||
use internals::{impl_to_hex_from_lower_hex, write_err};
|
use internals::{impl_to_hex_from_lower_hex, write_err};
|
||||||
use io::Write;
|
use io::Write;
|
||||||
|
@ -293,6 +295,41 @@ impl From<DecodeError> for ParseSignatureError {
|
||||||
fn from(e: DecodeError) -> Self { Self::Decode(e) }
|
fn from(e: DecodeError) -> Self { Self::Decode(e) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for Signature {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
// The valid range of r and s should be between 0 and n-1 where
|
||||||
|
// n = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
|
||||||
|
let high_min = 0x0u128;
|
||||||
|
let high_max = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEu128;
|
||||||
|
let low_min = 0x0u128;
|
||||||
|
let low_max = 0xBAAEDCE6AF48A03BBFD25E8CD0364140u128;
|
||||||
|
|
||||||
|
// Equally weight the chances of getting a minimum value for a signature, maximum value for
|
||||||
|
// a signature, and an arbitrary valid signature
|
||||||
|
let choice = u.int_in_range(0..=2)?;
|
||||||
|
let (high, low) = match choice {
|
||||||
|
0 => (high_min, low_min),
|
||||||
|
1 => (high_max, low_max),
|
||||||
|
_ => (u.int_in_range(high_min..=high_max)?, u.int_in_range(low_min..=low_max)?),
|
||||||
|
};
|
||||||
|
|
||||||
|
// We can use the same bytes for r and s since they're just arbitrary values
|
||||||
|
let mut bytes: [u8; 32] = [0; 32];
|
||||||
|
bytes[..16].copy_from_slice(&high.to_be_bytes());
|
||||||
|
bytes[16..].copy_from_slice(&low.to_be_bytes());
|
||||||
|
|
||||||
|
let mut signature_bytes: [u8; 64] = [0; 64];
|
||||||
|
signature_bytes[..32].copy_from_slice(&bytes);
|
||||||
|
signature_bytes[32..].copy_from_slice(&bytes);
|
||||||
|
|
||||||
|
Ok(Signature{
|
||||||
|
signature: secp256k1::ecdsa::Signature::from_compact(&signature_bytes).unwrap(),
|
||||||
|
sighash_type: EcdsaSighashType::arbitrary(u)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
use core::{fmt, str};
|
use core::{fmt, str};
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
use arbitrary::{Arbitrary, Unstructured};
|
||||||
use hashes::{hash_newtype, sha256, sha256d, sha256t, sha256t_tag};
|
use hashes::{hash_newtype, sha256, sha256d, sha256t, sha256t_tag};
|
||||||
use internals::write_err;
|
use internals::write_err;
|
||||||
use io::Write;
|
use io::Write;
|
||||||
|
@ -1467,6 +1469,37 @@ impl<E: std::error::Error + 'static> std::error::Error for SigningDataError<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for EcdsaSighashType {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
let choice = u.int_in_range(0..=5)?;
|
||||||
|
match choice {
|
||||||
|
0 => Ok(EcdsaSighashType::All),
|
||||||
|
1 => Ok(EcdsaSighashType::None),
|
||||||
|
2 => Ok(EcdsaSighashType::Single),
|
||||||
|
3 => Ok(EcdsaSighashType::AllPlusAnyoneCanPay),
|
||||||
|
4 => Ok(EcdsaSighashType::NonePlusAnyoneCanPay),
|
||||||
|
_ => Ok(EcdsaSighashType::SinglePlusAnyoneCanPay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for TapSighashType {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
let choice = u.int_in_range(0..=6)?;
|
||||||
|
match choice {
|
||||||
|
0 => Ok(TapSighashType::Default),
|
||||||
|
1 => Ok(TapSighashType::All),
|
||||||
|
2 => Ok(TapSighashType::None),
|
||||||
|
3 => Ok(TapSighashType::Single),
|
||||||
|
4 => Ok(TapSighashType::AllPlusAnyoneCanPay),
|
||||||
|
5 => Ok(TapSighashType::NonePlusAnyoneCanPay),
|
||||||
|
_ => Ok(TapSighashType::SinglePlusAnyoneCanPay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use hashes::HashEngine;
|
use hashes::HashEngine;
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
use arbitrary::{Arbitrary, Unstructured};
|
||||||
use internals::write_err;
|
use internals::write_err;
|
||||||
use io::Write;
|
use io::Write;
|
||||||
|
|
||||||
|
@ -133,3 +135,15 @@ impl From<secp256k1::Error> for SigFromSliceError {
|
||||||
impl From<InvalidSighashTypeError> for SigFromSliceError {
|
impl From<InvalidSighashTypeError> for SigFromSliceError {
|
||||||
fn from(err: InvalidSighashTypeError) -> Self { Self::SighashType(err) }
|
fn from(err: InvalidSighashTypeError) -> Self { Self::SighashType(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for Signature {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
let arbitrary_bytes: [u8; secp256k1::constants::SCHNORR_SIGNATURE_SIZE] = u.arbitrary()?;
|
||||||
|
|
||||||
|
Ok(Signature {
|
||||||
|
signature: secp256k1::schnorr::Signature::from_slice(&arbitrary_bytes).unwrap(),
|
||||||
|
sighash_type: TapSighashType::arbitrary(u)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue