Implement Arbitrary for Transaction
This commit is contained in:
parent
fe2985baf7
commit
5b4e81b379
|
@ -110,6 +110,7 @@ dependencies = [
|
||||||
name = "bitcoin-primitives"
|
name = "bitcoin-primitives"
|
||||||
version = "0.100.0"
|
version = "0.100.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"arbitrary",
|
||||||
"bitcoin-internals",
|
"bitcoin-internals",
|
||||||
"bitcoin-io",
|
"bitcoin-io",
|
||||||
"bitcoin-units",
|
"bitcoin-units",
|
||||||
|
|
|
@ -109,6 +109,7 @@ dependencies = [
|
||||||
name = "bitcoin-primitives"
|
name = "bitcoin-primitives"
|
||||||
version = "0.100.0"
|
version = "0.100.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"arbitrary",
|
||||||
"bitcoin-internals",
|
"bitcoin-internals",
|
||||||
"bitcoin-io",
|
"bitcoin-io",
|
||||||
"bitcoin-units",
|
"bitcoin-units",
|
||||||
|
|
|
@ -22,7 +22,7 @@ rand = ["secp256k1/rand"]
|
||||||
serde = ["dep:serde", "hashes/serde", "internals/serde", "primitives/serde", "secp256k1/serde", "units/serde"]
|
serde = ["dep:serde", "hashes/serde", "internals/serde", "primitives/serde", "secp256k1/serde", "units/serde"]
|
||||||
secp-lowmemory = ["secp256k1/lowmemory"]
|
secp-lowmemory = ["secp256k1/lowmemory"]
|
||||||
secp-recovery = ["secp256k1/recovery"]
|
secp-recovery = ["secp256k1/recovery"]
|
||||||
arbitrary = ["dep:arbitrary", "units/arbitrary"]
|
arbitrary = ["dep:arbitrary", "units/arbitrary", "primitives/arbitrary"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base58 = { package = "base58ck", version = "0.1.0", default-features = false, features = ["alloc"] }
|
base58 = { package = "base58ck", version = "0.1.0", default-features = false, features = ["alloc"] }
|
||||||
|
|
|
@ -1409,6 +1409,42 @@ impl InputWeightPrediction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for OutPoint {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
Ok(OutPoint{
|
||||||
|
txid: Txid::arbitrary(u)?,
|
||||||
|
vout: u32::arbitrary(u)?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for TxIn {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
Ok(TxIn{
|
||||||
|
previous_output: OutPoint::arbitrary(u)?,
|
||||||
|
script_sig: ScriptBuf::arbitrary(u)?,
|
||||||
|
sequence: Sequence::arbitrary(u)?,
|
||||||
|
witness: Witness::arbitrary(u)?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for Transaction {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
use primitives::absolute::LockTime;
|
||||||
|
|
||||||
|
Ok(Transaction {
|
||||||
|
version: Version::arbitrary(u)?,
|
||||||
|
lock_time: LockTime::arbitrary(u)?,
|
||||||
|
input: Vec::<TxIn>::arbitrary(u)?,
|
||||||
|
output: Vec::<TxOut>::arbitrary(u)?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use hex::{test_hex_unwrap as hex, FromHex};
|
use hex::{test_hex_unwrap as hex, FromHex};
|
||||||
|
|
|
@ -18,6 +18,8 @@ use crate::prelude::Vec;
|
||||||
use crate::script::ScriptExt as _;
|
use crate::script::ScriptExt as _;
|
||||||
use crate::taproot::{self, TAPROOT_ANNEX_PREFIX};
|
use crate::taproot::{self, TAPROOT_ANNEX_PREFIX};
|
||||||
use crate::{Script, VarInt};
|
use crate::{Script, VarInt};
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
use arbitrary::{Arbitrary, Unstructured};
|
||||||
|
|
||||||
/// The Witness is the data used to unlock bitcoin since the [segwit upgrade].
|
/// The Witness is the data used to unlock bitcoin since the [segwit upgrade].
|
||||||
///
|
///
|
||||||
|
@ -618,6 +620,14 @@ impl Default for Witness {
|
||||||
fn default() -> Self { Self::new() }
|
fn default() -> Self { Self::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for Witness {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
let arbitrary_bytes = Vec::<Vec::<u8>>::arbitrary(u)?;
|
||||||
|
Ok(Witness::from_slice(&arbitrary_bytes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use hex::test_hex_unwrap as hex;
|
use hex::test_hex_unwrap as hex;
|
||||||
|
|
|
@ -19,8 +19,10 @@ default = ["std"]
|
||||||
std = ["alloc", "hashes/std", "internals/std", "io/std", "units/std"]
|
std = ["alloc", "hashes/std", "internals/std", "io/std", "units/std"]
|
||||||
alloc = ["hashes/alloc", "internals/alloc", "io/alloc", "units/alloc"]
|
alloc = ["hashes/alloc", "internals/alloc", "io/alloc", "units/alloc"]
|
||||||
serde = ["dep:serde", "hashes/serde", "internals/serde", "units/serde", "alloc"]
|
serde = ["dep:serde", "hashes/serde", "internals/serde", "units/serde", "alloc"]
|
||||||
|
arbitrary = ["dep:arbitrary", "units/arbitrary"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
arbitrary = { version = "1", optional = true }
|
||||||
hashes = { package = "bitcoin_hashes", version = "0.14.0", default-features = false, features = ["bitcoin-io"] }
|
hashes = { package = "bitcoin_hashes", version = "0.14.0", default-features = false, features = ["bitcoin-io"] }
|
||||||
internals = { package = "bitcoin-internals", version = "0.3.0" }
|
internals = { package = "bitcoin-internals", version = "0.3.0" }
|
||||||
io = { package = "bitcoin-io", version = "0.1.1", default-features = false }
|
io = { package = "bitcoin-io", version = "0.1.1", default-features = false }
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
|
|
||||||
# Test these features with "std" enabled.
|
# Test these features with "std" enabled.
|
||||||
FEATURES_WITH_STD="ordered serde"
|
FEATURES_WITH_STD="ordered serde arbitrary"
|
||||||
|
|
||||||
# Test these features without "std" enabled.
|
# Test these features without "std" enabled.
|
||||||
FEATURES_WITHOUT_STD="alloc ordered serde"
|
FEATURES_WITHOUT_STD="alloc ordered serde arbitrary"
|
||||||
|
|
||||||
# Run these examples.
|
# Run these examples.
|
||||||
EXAMPLES=""
|
EXAMPLES=""
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
use arbitrary::{Arbitrary, Unstructured};
|
||||||
#[cfg(all(test, mutate))]
|
#[cfg(all(test, mutate))]
|
||||||
use mutagen::mutate;
|
use mutagen::mutate;
|
||||||
use units::parse::{self, PrefixedHexError, UnprefixedHexError};
|
use units::parse::{self, PrefixedHexError, UnprefixedHexError};
|
||||||
|
@ -395,6 +397,14 @@ impl ordered::ArbitraryOrd for LockTime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for LockTime {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
let l = u32::arbitrary(u)?;
|
||||||
|
Ok(LockTime::from_consensus(l))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -24,6 +24,8 @@ use serde::{Deserialize, Serialize};
|
||||||
use units::locktime::relative::TimeOverflowError;
|
use units::locktime::relative::TimeOverflowError;
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use units::parse::{self, PrefixedHexError, UnprefixedHexError};
|
use units::parse::{self, PrefixedHexError, UnprefixedHexError};
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
use arbitrary::{Arbitrary, Unstructured};
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use crate::locktime::relative;
|
use crate::locktime::relative;
|
||||||
|
@ -238,3 +240,11 @@ impl fmt::Debug for Sequence {
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
units::impl_parse_str_from_int_infallible!(Sequence, u32, from_consensus);
|
units::impl_parse_str_from_int_infallible!(Sequence, u32, from_consensus);
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for Sequence {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
let s = u32::arbitrary(u)?;
|
||||||
|
Ok(Sequence(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
use hashes::sha256d;
|
use hashes::sha256d;
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
use arbitrary::{Arbitrary, Unstructured};
|
||||||
|
|
||||||
hashes::hash_newtype! {
|
hashes::hash_newtype! {
|
||||||
/// A bitcoin transaction hash/transaction ID.
|
/// A bitcoin transaction hash/transaction ID.
|
||||||
|
@ -70,3 +72,20 @@ impl Version {
|
||||||
impl fmt::Display for Version {
|
impl fmt::Display for Version {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for Version {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
let v = i32::arbitrary(u)?;
|
||||||
|
Ok(Version(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for Txid {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
let arbitrary_bytes = u.arbitrary()?;
|
||||||
|
let t = sha256d::Hash::from_byte_array(arbitrary_bytes);
|
||||||
|
Ok(Txid(t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue