1use core::convert::Infallible;
15#[cfg(feature = "encoding")]
16use core::mem;
17use core::str::FromStr;
18use core::{cmp, fmt};
19
20#[cfg(feature = "encoding")]
21use encoding::{
22 ArrayEncoder, BytesEncoder, CompactSizeEncoder, Decoder2, Decoder3, DecoderStatus, Encode as _,
23 Encoder2, Encoder3, Encoder6, EncoderStatus, SliceEncoder, VecDecoder,
24};
25use hashes::{sha256d, Hash};
26use io::{Read, Write};
27#[cfg(feature = "encoding")]
28use units::amount::{AmountDecoder, AmountEncoder};
29use units::parse::{self, ParseIntError};
30
31use super::Weight;
32use crate::blockdata::locktime::absolute::{self, Height, Time};
33#[cfg(feature = "encoding")]
34use crate::blockdata::locktime::absolute::{
35 LockTimeDecoder, LockTimeDecoderError, LockTimeEncoder,
36};
37use crate::blockdata::locktime::relative::{self, TimeOverflowError};
38use crate::blockdata::script::{Script, ScriptBuf};
39#[cfg(feature = "encoding")]
40use crate::blockdata::script::{ScriptBufDecoder, ScriptEncoder};
41use crate::blockdata::witness::Witness;
42#[cfg(feature = "encoding")]
43use crate::blockdata::witness::{WitnessDecoder, WitnessDecoderError, WitnessEncoder};
44use crate::blockdata::FeeRate;
45use crate::consensus::{encode, Decodable, Encodable};
46use crate::error::{ContainsPrefixError, MissingPrefixError, PrefixedHexError, UnprefixedHexError};
47use crate::internal_macros::{impl_consensus_encoding, impl_hashencode, write_err};
48use crate::prelude::*;
49#[cfg(doc)]
50use crate::sighash::{EcdsaSighashType, TapSighashType};
51use crate::{Amount, SignedAmount, VarInt};
52
53#[rustfmt::skip] #[cfg(feature = "bitcoinconsensus")]
55#[doc(inline)]
56pub use crate::consensus::validation::TxVerifyError;
57
58#[cfg(feature = "arbitrary")]
59use actual_arbitrary::{self as arbitrary, Arbitrary, Unstructured};
60
61hashes::hash_newtype! {
62 pub struct Txid(sha256d::Hash);
69
70 pub struct Wtxid(sha256d::Hash);
72}
73impl_hashencode!(Txid);
74impl_hashencode!(Wtxid);
75
76const SEGWIT_MARKER: u8 = 0x00;
78const SEGWIT_FLAG: u8 = 0x01;
80
81#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
87pub struct OutPoint {
88 pub txid: Txid,
90 pub vout: u32,
92}
93#[cfg(feature = "serde")]
94crate::serde_utils::serde_struct_human_string_impl!(OutPoint, "an OutPoint", txid, vout);
95
96impl OutPoint {
97 const SIZE: usize = 32 + 4; #[inline]
102 pub const fn new(txid: Txid, vout: u32) -> OutPoint { OutPoint { txid, vout } }
103
104 #[inline]
108 pub fn null() -> OutPoint { OutPoint { txid: Hash::all_zeros(), vout: u32::MAX } }
109
110 #[inline]
126 pub fn is_null(&self) -> bool { *self == OutPoint::null() }
127}
128
129impl Default for OutPoint {
130 fn default() -> Self { OutPoint::null() }
131}
132
133impl fmt::Display for OutPoint {
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 write!(f, "{}:{}", self.txid, self.vout)
136 }
137}
138
139#[derive(Debug, Clone, PartialEq, Eq)]
141#[non_exhaustive]
142pub enum ParseOutPointError {
143 Txid(hex::HexToArrayError),
145 Vout(crate::error::ParseIntError),
147 Format,
149 TooLong,
151 VoutNotCanonical,
153}
154
155impl From<Infallible> for ParseOutPointError {
156 fn from(never: Infallible) -> Self { match never {} }
157}
158
159impl fmt::Display for ParseOutPointError {
160 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
161 use ParseOutPointError::*;
162
163 match *self {
164 Txid(ref e) => write_err!(f, "error parsing TXID"; e),
165 Vout(ref e) => write_err!(f, "error parsing vout"; e),
166 Format => write!(f, "OutPoint not in <txid>:<vout> format"),
167 TooLong => write!(f, "vout should be at most 10 digits"),
168 VoutNotCanonical => write!(f, "no leading zeroes or + allowed in vout part"),
169 }
170 }
171}
172
173#[cfg(feature = "std")]
174impl std::error::Error for ParseOutPointError {
175 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
176 use ParseOutPointError::*;
177
178 match self {
179 Txid(e) => Some(e),
180 Vout(e) => Some(e),
181 Format | TooLong | VoutNotCanonical => None,
182 }
183 }
184}
185
186fn parse_vout(s: &str) -> Result<u32, ParseOutPointError> {
190 if s.len() > 1 {
191 let first = s.chars().next().unwrap();
192 if first == '0' || first == '+' {
193 return Err(ParseOutPointError::VoutNotCanonical);
194 }
195 }
196 parse::int(s).map_err(ParseOutPointError::Vout)
197}
198
199impl core::str::FromStr for OutPoint {
200 type Err = ParseOutPointError;
201
202 fn from_str(s: &str) -> Result<Self, Self::Err> {
203 if s.len() > 75 {
204 return Err(ParseOutPointError::TooLong);
206 }
207 let find = s.find(':');
208 if find.is_none() || find != s.rfind(':') {
209 return Err(ParseOutPointError::Format);
210 }
211 let colon = find.unwrap();
212 if colon == 0 || colon == s.len() - 1 {
213 return Err(ParseOutPointError::Format);
214 }
215 Ok(OutPoint {
216 txid: s[..colon].parse().map_err(ParseOutPointError::Txid)?,
217 vout: parse_vout(&s[colon + 1..])?,
218 })
219 }
220}
221
222#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
233#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
234pub struct TxIn {
235 pub previous_output: OutPoint,
237 pub script_sig: ScriptBuf,
240 pub sequence: Sequence,
245 pub witness: Witness,
251}
252
253impl TxIn {
254 const BASE_WEIGHT: Weight =
258 Weight::from_vb_unwrap(OutPoint::SIZE as u64 + Sequence::SIZE as u64);
259
260 pub fn enables_lock_time(&self) -> bool { self.sequence != Sequence::MAX }
270
271 pub fn legacy_weight(&self) -> Weight {
281 Weight::from_non_witness_data_size(self.base_size() as u64)
282 }
283
284 pub fn segwit_weight(&self) -> Weight {
296 Weight::from_non_witness_data_size(self.base_size() as u64)
297 + Weight::from_witness_data_size(self.witness.size() as u64)
298 }
299
300 pub fn base_size(&self) -> usize {
304 let mut size = OutPoint::SIZE;
305
306 size += VarInt::from(self.script_sig.len()).size();
307 size += self.script_sig.len();
308
309 size + Sequence::SIZE
310 }
311
312 pub fn total_size(&self) -> usize { self.base_size() + self.witness.size() }
316}
317
318impl Default for TxIn {
319 fn default() -> TxIn {
320 TxIn {
321 previous_output: OutPoint::default(),
322 script_sig: ScriptBuf::new(),
323 sequence: Sequence::MAX,
324 witness: Witness::default(),
325 }
326 }
327}
328
329#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
344#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
345#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
346pub struct Sequence(pub u32);
347
348impl Sequence {
349 pub const MAX: Self = Sequence(0xFFFFFFFF);
353 pub const ZERO: Self = Sequence(0);
357 pub const ENABLE_LOCKTIME_NO_RBF: Self = Sequence::MIN_NO_RBF;
360 pub const ENABLE_RBF_NO_LOCKTIME: Self = Sequence(0xFFFFFFFD);
363
364 const SIZE: usize = 4; const MIN_NO_RBF: Self = Sequence(0xFFFFFFFE);
375 const LOCK_TIME_DISABLE_FLAG_MASK: u32 = 0x80000000;
377 const LOCK_TYPE_MASK: u32 = 0x00400000;
379
380 #[inline]
382 pub fn enables_absolute_lock_time(&self) -> bool { *self != Sequence::MAX }
383
384 #[inline]
404 pub fn is_final(&self) -> bool { !self.enables_absolute_lock_time() }
405
406 #[inline]
411 pub fn is_rbf(&self) -> bool { *self < Sequence::MIN_NO_RBF }
412
413 #[inline]
415 pub fn is_relative_lock_time(&self) -> bool {
416 self.0 & Sequence::LOCK_TIME_DISABLE_FLAG_MASK == 0
417 }
418
419 #[inline]
421 pub fn is_height_locked(&self) -> bool {
422 self.is_relative_lock_time() & (self.0 & Sequence::LOCK_TYPE_MASK == 0)
423 }
424
425 #[inline]
427 pub fn is_time_locked(&self) -> bool {
428 self.is_relative_lock_time() & (self.0 & Sequence::LOCK_TYPE_MASK > 0)
429 }
430
431 pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
433 let stripped = if let Some(stripped) = s.strip_prefix("0x") {
434 stripped
435 } else if let Some(stripped) = s.strip_prefix("0X") {
436 stripped
437 } else {
438 return Err(MissingPrefixError::new(s).into());
439 };
440
441 let sequence = parse::hex_u32(stripped)?;
442 Ok(Self::from_consensus(sequence))
443 }
444
445 pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
447 if s.starts_with("0x") || s.starts_with("0X") {
448 return Err(ContainsPrefixError::new(s).into());
449 }
450 let lock_time = parse::hex_u32(s)?;
451 Ok(Self::from_consensus(lock_time))
452 }
453
454 #[inline]
456 pub fn from_height(height: u16) -> Self { Sequence(u32::from(height)) }
457
458 #[inline]
463 pub fn from_512_second_intervals(intervals: u16) -> Self {
464 Sequence(u32::from(intervals) | Sequence::LOCK_TYPE_MASK)
465 }
466
467 #[inline]
472 pub fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError> {
473 if let Ok(interval) = u16::try_from(seconds / 512) {
474 Ok(Sequence::from_512_second_intervals(interval))
475 } else {
476 Err(TimeOverflowError::new(seconds))
477 }
478 }
479
480 #[inline]
485 pub fn from_seconds_ceil(seconds: u32) -> Result<Self, TimeOverflowError> {
486 if let Ok(interval) = u16::try_from((seconds + 511) / 512) {
487 Ok(Sequence::from_512_second_intervals(interval))
488 } else {
489 Err(TimeOverflowError::new(seconds))
490 }
491 }
492
493 #[inline]
495 pub fn from_consensus(n: u32) -> Self { Sequence(n) }
496
497 #[inline]
499 pub fn to_consensus_u32(self) -> u32 { self.0 }
500
501 #[inline]
503 pub fn to_relative_lock_time(&self) -> Option<relative::LockTime> {
504 use crate::locktime::relative::{Height, LockTime, Time};
505
506 if !self.is_relative_lock_time() {
507 return None;
508 }
509
510 let lock_value = self.low_u16();
511
512 if self.is_time_locked() {
513 Some(LockTime::from(Time::from_512_second_intervals(lock_value)))
514 } else {
515 Some(LockTime::from(Height::from(lock_value)))
516 }
517 }
518
519 fn low_u16(&self) -> u16 { self.0 as u16 }
523}
524
525impl Default for Sequence {
526 fn default() -> Self { Sequence::MAX }
528}
529
530impl From<Sequence> for u32 {
531 fn from(sequence: Sequence) -> u32 { sequence.0 }
532}
533
534impl fmt::Display for Sequence {
535 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
536}
537
538impl fmt::LowerHex for Sequence {
539 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
540}
541
542impl fmt::UpperHex for Sequence {
543 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
544}
545
546impl fmt::Debug for Sequence {
547 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
548 write!(f, "Sequence({:#010x})", self.0)
550 }
551}
552
553impl FromStr for Sequence {
554 type Err = ParseIntError;
555
556 fn from_str(s: &str) -> Result<Self, Self::Err> {
557 parse::int::<u32, &str>(s).map(Sequence::from_consensus)
558 }
559}
560
561impl TryFrom<&str> for Sequence {
562 type Error = ParseIntError;
563
564 fn try_from(s: &str) -> Result<Self, Self::Error> { Sequence::from_str(s) }
565}
566
567impl TryFrom<String> for Sequence {
568 type Error = ParseIntError;
569
570 fn try_from(s: String) -> Result<Self, Self::Error> { Sequence::from_str(&s) }
571}
572
573impl TryFrom<Box<str>> for Sequence {
574 type Error = ParseIntError;
575
576 fn try_from(s: Box<str>) -> Result<Self, Self::Error> { Sequence::from_str(&s) }
577}
578
579#[cfg(feature = "encoding")]
580impl encoding::Encode for Sequence {
581 type Encoder<'e> = SequenceEncoder<'e>;
582 #[inline]
583 fn encoder(&self) -> Self::Encoder<'_> {
584 SequenceEncoder::new(encoding::ArrayEncoder::without_length_prefix(
585 self.to_consensus_u32().to_le_bytes(),
586 ))
587 }
588}
589
590#[cfg(feature = "encoding")]
591impl encoding::Decode for Sequence {
592 type Decoder = SequenceDecoder;
593}
594
595#[cfg(feature = "encoding")]
596encoding::encoder_newtype_exact! {
597 #[derive(Debug, Clone)]
599 pub struct SequenceEncoder<'e>(encoding::ArrayEncoder<4>);
600}
601
602#[cfg(feature = "encoding")]
603crate::decoder_newtype! {
604 #[derive(Debug, Clone)]
606 pub struct SequenceDecoder(encoding::ArrayDecoder<4>);
607
608 pub const fn new() -> Self { Self(encoding::ArrayDecoder::new()) }
610
611 fn end(result: Result<[u8; 4], encoding::UnexpectedEofError>) -> Result<Sequence, SequenceDecoderError> {
612 let value = result.map_err(SequenceDecoderError)?;
613 let n = u32::from_le_bytes(value);
614 Ok(Sequence::from_consensus(n))
615 }
616}
617
618#[cfg(feature = "encoding")]
620#[derive(Debug, Clone, PartialEq, Eq)]
621pub struct SequenceDecoderError(pub(super) encoding::UnexpectedEofError);
622
623#[cfg(feature = "encoding")]
624impl From<Infallible> for SequenceDecoderError {
625 fn from(never: Infallible) -> Self { match never {} }
626}
627
628#[cfg(feature = "encoding")]
629impl fmt::Display for SequenceDecoderError {
630 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
631 write_err!(f, "sequence decoder error"; self.0)
632 }
633}
634
635#[cfg(all(feature = "std", feature = "encoding"))]
636impl std::error::Error for SequenceDecoderError {
637 #[inline]
638 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
639}
640
641#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
653#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
654#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
655pub struct TxOut {
656 pub value: Amount,
658 pub script_pubkey: ScriptBuf,
660}
661
662impl TxOut {
663 pub const NULL: Self =
665 TxOut { value: Amount::from_sat(0xffffffffffffffff), script_pubkey: ScriptBuf::new() };
666
667 pub fn weight(&self) -> Weight {
678 Weight::from_vb(self.size() as u64).expect("should never happen under normal conditions")
680 }
681
682 pub fn size(&self) -> usize { size_from_script_pubkey(&self.script_pubkey) }
686
687 pub fn minimal_non_dust(script_pubkey: ScriptBuf) -> Self {
697 TxOut { value: script_pubkey.minimal_non_dust(), script_pubkey }
698 }
699
700 pub fn minimal_non_dust_custom(script_pubkey: ScriptBuf, dust_relay_fee: FeeRate) -> Self {
712 TxOut { value: script_pubkey.minimal_non_dust_custom(dust_relay_fee), script_pubkey }
713 }
714}
715
716fn size_from_script_pubkey(script_pubkey: &Script) -> usize {
718 let len = script_pubkey.len();
719 Amount::SIZE + VarInt::from(len).size() + len
720}
721
722#[derive(Clone, PartialEq, Eq, Debug, Hash)]
778#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
779#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
780pub struct Transaction {
781 pub version: Version,
783 pub lock_time: absolute::LockTime,
790 pub input: Vec<TxIn>,
792 pub output: Vec<TxOut>,
794}
795
796impl cmp::PartialOrd for Transaction {
797 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { Some(self.cmp(other)) }
798}
799impl cmp::Ord for Transaction {
800 fn cmp(&self, other: &Self) -> cmp::Ordering {
801 self.version
802 .cmp(&other.version)
803 .then(self.lock_time.to_consensus_u32().cmp(&other.lock_time.to_consensus_u32()))
804 .then(self.input.cmp(&other.input))
805 .then(self.output.cmp(&other.output))
806 }
807}
808
809impl Transaction {
810 pub const MAX_STANDARD_WEIGHT: Weight = Weight::from_wu(400_000);
813
814 #[deprecated(
818 since = "0.31.0",
819 note = "ntxid has been renamed to compute_ntxid to note that it's computationally expensive. use compute_ntxid() instead."
820 )]
821 pub fn ntxid(&self) -> sha256d::Hash { self.compute_ntxid() }
822
823 #[doc(alias = "ntxid")]
828 pub fn compute_ntxid(&self) -> sha256d::Hash {
829 let cloned_tx = Transaction {
830 version: self.version,
831 lock_time: self.lock_time,
832 input: self
833 .input
834 .iter()
835 .map(|txin| TxIn {
836 script_sig: ScriptBuf::new(),
837 witness: Witness::default(),
838 ..*txin
839 })
840 .collect(),
841 output: self.output.clone(),
842 };
843 cloned_tx.compute_txid().into()
844 }
845
846 #[deprecated(
850 since = "0.31.0",
851 note = "txid has been renamed to compute_txid to note that it's computationally expensive. use compute_txid() instead."
852 )]
853 pub fn txid(&self) -> Txid { self.compute_txid() }
854
855 #[doc(alias = "txid")]
861 pub fn compute_txid(&self) -> Txid {
862 let mut enc = Txid::engine();
863 self.version.consensus_encode(&mut enc).expect("engines don't error");
864 self.input.consensus_encode(&mut enc).expect("engines don't error");
865 self.output.consensus_encode(&mut enc).expect("engines don't error");
866 self.lock_time.consensus_encode(&mut enc).expect("engines don't error");
867 Txid::from_engine(enc)
868 }
869
870 #[deprecated(
874 since = "0.31.0",
875 note = "wtxid has been renamed to compute_wtxid to note that it's computationally expensive. use compute_wtxid() instead."
876 )]
877 pub fn wtxid(&self) -> Wtxid { self.compute_wtxid() }
878
879 #[doc(alias = "wtxid")]
885 pub fn compute_wtxid(&self) -> Wtxid {
886 let mut enc = Wtxid::engine();
887 self.consensus_encode(&mut enc).expect("engines don't error");
888 Wtxid::from_engine(enc)
889 }
890
891 #[inline]
910 pub fn weight(&self) -> Weight {
911 let wu = self.base_size() * 3 + self.total_size();
913 Weight::from_wu_usize(wu)
914 }
915
916 pub fn base_size(&self) -> usize {
920 let mut size: usize = 4; size += VarInt::from(self.input.len()).size();
923 size += self.input.iter().map(|input| input.base_size()).sum::<usize>();
924
925 size += VarInt::from(self.output.len()).size();
926 size += self.output.iter().map(|output| output.size()).sum::<usize>();
927
928 size + absolute::LockTime::SIZE
929 }
930
931 #[inline]
936 pub fn total_size(&self) -> usize {
937 let mut size: usize = 4; let uses_segwit = self.uses_segwit_serialization();
939
940 if uses_segwit {
941 size += 2; }
943
944 size += VarInt::from(self.input.len()).size();
945 size += self
946 .input
947 .iter()
948 .map(|input| if uses_segwit { input.total_size() } else { input.base_size() })
949 .sum::<usize>();
950
951 size += VarInt::from(self.output.len()).size();
952 size += self.output.iter().map(|output| output.size()).sum::<usize>();
953
954 size + absolute::LockTime::SIZE
955 }
956
957 #[inline]
969 pub fn vsize(&self) -> usize {
970 self.weight().to_vbytes_ceil() as usize
972 }
973
974 #[doc(alias = "is_coin_base")] pub fn is_coinbase(&self) -> bool {
982 self.input.len() == 1 && self.input[0].previous_output.is_null()
983 }
984
985 pub fn is_explicitly_rbf(&self) -> bool {
995 self.input.iter().any(|input| input.sequence.is_rbf())
996 }
997
998 pub fn is_absolute_timelock_satisfied(&self, height: Height, time: Time) -> bool {
1006 if !self.is_lock_time_enabled() {
1007 return true;
1008 }
1009 self.lock_time.is_satisfied_by(height, time)
1010 }
1011
1012 pub fn is_lock_time_enabled(&self) -> bool { self.input.iter().any(|i| i.enables_lock_time()) }
1016
1017 pub fn script_pubkey_lens(&self) -> impl Iterator<Item = usize> + '_ {
1023 self.output.iter().map(|txout| txout.script_pubkey.len())
1024 }
1025
1026 pub fn total_sigop_cost<S>(&self, mut spent: S) -> usize
1039 where
1040 S: FnMut(&OutPoint) -> Option<TxOut>,
1041 {
1042 let mut cost = self.count_p2pk_p2pkh_sigops().saturating_mul(4);
1043
1044 cost = cost.saturating_add(self.count_p2sh_sigops(&mut spent).saturating_mul(4));
1046 cost.saturating_add(self.count_witness_sigops(&mut spent))
1047 }
1048
1049 fn count_p2pk_p2pkh_sigops(&self) -> usize {
1055 let mut count: usize = 0;
1056 for input in &self.input {
1057 count = count.saturating_add(input.script_sig.count_sigops_legacy());
1059 }
1060 for output in &self.output {
1061 count = count.saturating_add(output.script_pubkey.count_sigops_legacy());
1062 }
1063 count
1064 }
1065
1066 fn count_p2sh_sigops<S>(&self, spent: &mut S) -> usize
1068 where
1069 S: FnMut(&OutPoint) -> Option<TxOut>,
1070 {
1071 fn count_sigops(prevout: &TxOut, input: &TxIn) -> usize {
1072 let mut count: usize = 0;
1073 if prevout.script_pubkey.is_p2sh() {
1074 if let Some(redeem) = input.script_sig.last_pushdata() {
1075 count =
1076 count.saturating_add(Script::from_bytes(redeem.as_bytes()).count_sigops());
1077 }
1078 }
1079 count
1080 }
1081
1082 let mut count: usize = 0;
1083 for input in &self.input {
1084 if let Some(prevout) = spent(&input.previous_output) {
1085 count = count.saturating_add(count_sigops(&prevout, input));
1086 }
1087 }
1088 count
1089 }
1090
1091 fn count_witness_sigops<S>(&self, spent: &mut S) -> usize
1093 where
1094 S: FnMut(&OutPoint) -> Option<TxOut>,
1095 {
1096 fn count_sigops_with_witness_program(witness: &Witness, witness_program: &Script) -> usize {
1097 if witness_program.is_p2wpkh() {
1098 1
1099 } else if witness_program.is_p2wsh() {
1100 witness.last().map(Script::from_bytes).map(|s| s.count_sigops()).unwrap_or(0)
1102 } else {
1103 0
1104 }
1105 }
1106
1107 fn count_sigops(prevout: TxOut, input: &TxIn) -> usize {
1108 let script_sig = &input.script_sig;
1109 let witness = &input.witness;
1110
1111 let witness_program = if prevout.script_pubkey.is_witness_program() {
1112 &prevout.script_pubkey
1113 } else if prevout.script_pubkey.is_p2sh() && script_sig.is_push_only() {
1114 if let Some(push_bytes) = script_sig.last_pushdata() {
1117 Script::from_bytes(push_bytes.as_bytes())
1118 } else {
1119 return 0;
1120 }
1121 } else {
1122 return 0;
1123 };
1124
1125 count_sigops_with_witness_program(witness, witness_program)
1127 }
1128
1129 let mut count: usize = 0;
1130 for input in &self.input {
1131 if let Some(prevout) = spent(&input.previous_output) {
1132 count = count.saturating_add(count_sigops(prevout, input));
1133 }
1134 }
1135 count
1136 }
1137
1138 fn uses_segwit_serialization(&self) -> bool {
1140 if self.input.iter().any(|input| !input.witness.is_empty()) {
1141 return true;
1142 }
1143 self.input.is_empty()
1146 }
1147
1148 #[inline]
1150 pub fn tx_in(&self, input_index: usize) -> Result<&TxIn, InputsIndexError> {
1151 self.input
1152 .get(input_index)
1153 .ok_or(IndexOutOfBoundsError { index: input_index, length: self.input.len() }.into())
1154 }
1155
1156 #[inline]
1158 pub fn tx_out(&self, output_index: usize) -> Result<&TxOut, OutputsIndexError> {
1159 self.output
1160 .get(output_index)
1161 .ok_or(IndexOutOfBoundsError { index: output_index, length: self.output.len() }.into())
1162 }
1163}
1164
1165#[derive(Debug, Clone, PartialEq, Eq)]
1167pub struct InputsIndexError(pub IndexOutOfBoundsError);
1168
1169impl fmt::Display for InputsIndexError {
1170 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1171 write_err!(f, "invalid input index"; self.0)
1172 }
1173}
1174
1175#[cfg(feature = "std")]
1176impl std::error::Error for InputsIndexError {
1177 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
1178}
1179
1180impl From<IndexOutOfBoundsError> for InputsIndexError {
1181 fn from(e: IndexOutOfBoundsError) -> Self { Self(e) }
1182}
1183
1184#[derive(Debug, Clone, PartialEq, Eq)]
1186pub struct OutputsIndexError(pub IndexOutOfBoundsError);
1187
1188impl fmt::Display for OutputsIndexError {
1189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1190 write_err!(f, "invalid output index"; self.0)
1191 }
1192}
1193
1194#[cfg(feature = "std")]
1195impl std::error::Error for OutputsIndexError {
1196 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
1197}
1198
1199impl From<IndexOutOfBoundsError> for OutputsIndexError {
1200 fn from(e: IndexOutOfBoundsError) -> Self { Self(e) }
1201}
1202
1203#[derive(Debug, Clone, PartialEq, Eq)]
1205#[non_exhaustive]
1206pub struct IndexOutOfBoundsError {
1207 pub index: usize,
1209 pub length: usize,
1211}
1212
1213impl fmt::Display for IndexOutOfBoundsError {
1214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1215 write!(f, "index {} is out-of-bounds for vector with length {}", self.index, self.length)
1216 }
1217}
1218
1219#[cfg(feature = "std")]
1220impl std::error::Error for IndexOutOfBoundsError {
1221 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
1222}
1223
1224#[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)]
1234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1235#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
1236pub struct Version(pub i32);
1237
1238impl Version {
1239 pub const ONE: Self = Self(1);
1241
1242 pub const TWO: Self = Self(2);
1244
1245 pub fn non_standard(version: i32) -> Version { Self(version) }
1247
1248 pub fn is_standard(&self) -> bool { *self == Version::ONE || *self == Version::TWO }
1250}
1251
1252impl Encodable for Version {
1253 fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
1254 self.0.consensus_encode(w)
1255 }
1256}
1257
1258impl Decodable for Version {
1259 fn consensus_decode<R: Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
1260 Decodable::consensus_decode(r).map(Version)
1261 }
1262}
1263
1264impl fmt::Display for Version {
1265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
1266}
1267
1268#[cfg(feature = "encoding")]
1269encoding::encoder_newtype_exact! {
1270 #[derive(Debug, Clone)]
1272 pub struct VersionEncoder<'e>(encoding::ArrayEncoder<4>);
1273}
1274
1275#[cfg(feature = "encoding")]
1276impl encoding::Encode for Version {
1277 type Encoder<'e> = VersionEncoder<'e>;
1278 fn encoder(&self) -> Self::Encoder<'_> {
1279 VersionEncoder::new(encoding::ArrayEncoder::without_length_prefix(self.0.to_le_bytes()))
1280 }
1281}
1282
1283#[cfg(feature = "encoding")]
1284crate::decoder_newtype! {
1285 #[derive(Debug, Clone)]
1287 pub struct VersionDecoder(encoding::ArrayDecoder<4>);
1288
1289 pub const fn new() -> Self { Self(encoding::ArrayDecoder::new()) }
1291
1292 fn end(result: Result<[u8; 4], encoding::UnexpectedEofError>) -> Result<Version, VersionDecoderError> {
1293 let bytes = result.map_err(VersionDecoderError)?;
1294 let n = i32::from_le_bytes(bytes);
1295 Ok(Version::non_standard(n))
1296 }
1297}
1298
1299#[cfg(feature = "encoding")]
1300impl encoding::Decode for Version {
1301 type Decoder = VersionDecoder;
1302}
1303
1304#[cfg(feature = "encoding")]
1306#[derive(Debug, Clone, PartialEq, Eq)]
1307pub struct VersionDecoderError(pub(super) encoding::UnexpectedEofError);
1308
1309#[cfg(feature = "encoding")]
1310impl From<Infallible> for VersionDecoderError {
1311 fn from(never: Infallible) -> Self { match never {} }
1312}
1313
1314#[cfg(feature = "encoding")]
1315impl fmt::Display for VersionDecoderError {
1316 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1317 write_err!(f, "version decoder error"; self.0)
1318 }
1319}
1320
1321#[cfg(all(feature = "encoding", feature = "std"))]
1322impl std::error::Error for VersionDecoderError {
1323 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
1324}
1325
1326impl_consensus_encoding!(TxOut, value, script_pubkey);
1327
1328#[cfg(feature = "encoding")]
1329encoding::encoder_newtype_exact! {
1330 #[derive(Debug, Clone)]
1332 pub struct TxOutEncoder<'e>(Encoder2<AmountEncoder<'e>, ScriptEncoder<'e>>);
1333}
1334
1335#[cfg(feature = "encoding")]
1336impl encoding::Encode for TxOut {
1337 type Encoder<'e> = Encoder2<AmountEncoder<'e>, ScriptEncoder<'e>>;
1338
1339 fn encoder(&self) -> Self::Encoder<'_> {
1340 Encoder2::new(self.value.encoder(), self.script_pubkey.encoder())
1341 }
1342}
1343
1344#[cfg(feature = "encoding")]
1345type TxOutInnerDecoder = Decoder2<AmountDecoder, ScriptBufDecoder>;
1346
1347#[cfg(feature = "encoding")]
1348crate::decoder_newtype! {
1349 #[derive(Debug, Clone)]
1351 pub struct TxOutDecoder(TxOutInnerDecoder);
1352
1353 pub const fn new() -> Self {
1355 Self(Decoder2::new(AmountDecoder::new(), ScriptBufDecoder::new()))
1356 }
1357
1358 fn end(
1359 result: Result<<TxOutInnerDecoder as encoding::Decoder>::Output, <TxOutInnerDecoder as encoding::Decoder>::Error>
1360 ) -> Result<TxOut, TxOutDecoderError> {
1361 let (value, script_pubkey) = result.map_err(TxOutDecoderError)?;
1362 Ok(TxOut { value, script_pubkey })
1363 }
1364}
1365
1366#[cfg(feature = "encoding")]
1367impl encoding::Decode for TxOut {
1368 type Decoder = TxOutDecoder;
1369}
1370
1371#[cfg(feature = "encoding")]
1373#[derive(Debug, Clone, PartialEq, Eq)]
1374pub struct TxOutDecoderError(pub(super) <TxOutInnerDecoder as encoding::Decoder>::Error);
1375
1376#[cfg(feature = "encoding")]
1377impl From<Infallible> for TxOutDecoderError {
1378 fn from(never: Infallible) -> Self { match never {} }
1379}
1380
1381#[cfg(feature = "encoding")]
1382impl fmt::Display for TxOutDecoderError {
1383 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1384 write_err!(f, "txout decoder error"; self.0)
1385 }
1386}
1387
1388#[cfg(all(feature = "encoding", feature = "std"))]
1389impl std::error::Error for TxOutDecoderError {
1390 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
1391}
1392
1393impl Encodable for OutPoint {
1394 fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
1395 let len = self.txid.consensus_encode(w)?;
1396 Ok(len + self.vout.consensus_encode(w)?)
1397 }
1398}
1399impl Decodable for OutPoint {
1400 fn consensus_decode<R: Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
1401 Ok(OutPoint {
1402 txid: Decodable::consensus_decode(r)?,
1403 vout: Decodable::consensus_decode(r)?,
1404 })
1405 }
1406}
1407
1408#[cfg(feature = "encoding")]
1409encoding::encoder_newtype_exact! {
1410 #[derive(Debug, Clone)]
1412 pub struct OutPointEncoder<'e>(Encoder2<BytesEncoder<'e>, ArrayEncoder<4>>);
1413}
1414
1415#[cfg(feature = "encoding")]
1416impl encoding::Encode for OutPoint {
1417 type Encoder<'e> = OutPointEncoder<'e>;
1418
1419 fn encoder(&self) -> Self::Encoder<'_> {
1420 OutPointEncoder::new(Encoder2::new(
1421 BytesEncoder::without_length_prefix(self.txid.as_byte_array()),
1422 ArrayEncoder::without_length_prefix(self.vout.to_le_bytes()),
1423 ))
1424 }
1425}
1426
1427#[cfg(feature = "encoding")]
1428crate::decoder_newtype! {
1429 #[derive(Debug, Clone)]
1432 pub struct OutPointDecoder(encoding::ArrayDecoder<36>);
1433
1434 pub const fn new() -> Self { Self(encoding::ArrayDecoder::new()) }
1436
1437 fn end(result: Result<[u8; 36], encoding::UnexpectedEofError>) -> Result<OutPoint, OutPointDecoderError> {
1438 let encoded = result.map_err(OutPointDecoderError)?;
1439 let txid_buf: [u8; 32] = encoded[..32].try_into().expect("32 bytes");
1440 let vout_buf: [u8; 4] = encoded[32..].try_into().expect("4 bytes");
1441
1442 let txid = Txid::from_byte_array(txid_buf);
1443 let vout = u32::from_le_bytes(vout_buf);
1444
1445 Ok(OutPoint { txid, vout })
1446 }
1447}
1448
1449#[cfg(feature = "encoding")]
1450impl encoding::Decode for OutPoint {
1451 type Decoder = OutPointDecoder;
1452}
1453
1454#[cfg(feature = "encoding")]
1456#[derive(Debug, Clone, PartialEq, Eq)]
1457pub struct OutPointDecoderError(pub(crate) encoding::UnexpectedEofError);
1458
1459#[cfg(feature = "encoding")]
1460impl From<Infallible> for OutPointDecoderError {
1461 fn from(never: Infallible) -> Self { match never {} }
1462}
1463
1464#[cfg(feature = "encoding")]
1465impl core::fmt::Display for OutPointDecoderError {
1466 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1467 write_err!(f, "out point decoder error"; self.0)
1468 }
1469}
1470
1471#[cfg(all(feature = "encoding", feature = "std"))]
1472impl std::error::Error for OutPointDecoderError {
1473 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
1474}
1475
1476impl Encodable for TxIn {
1477 fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
1478 let mut len = 0;
1479 len += self.previous_output.consensus_encode(w)?;
1480 len += self.script_sig.consensus_encode(w)?;
1481 len += self.sequence.consensus_encode(w)?;
1482 Ok(len)
1483 }
1484}
1485impl Decodable for TxIn {
1486 #[inline]
1487 fn consensus_decode_from_finite_reader<R: Read + ?Sized>(
1488 r: &mut R,
1489 ) -> Result<Self, encode::Error> {
1490 Ok(TxIn {
1491 previous_output: Decodable::consensus_decode_from_finite_reader(r)?,
1492 script_sig: Decodable::consensus_decode_from_finite_reader(r)?,
1493 sequence: Decodable::consensus_decode_from_finite_reader(r)?,
1494 witness: Witness::default(),
1495 })
1496 }
1497}
1498
1499#[cfg(feature = "encoding")]
1500encoding::encoder_newtype_exact! {
1501 #[derive(Debug, Clone)]
1503 pub struct TxInEncoder<'e>(
1504 Encoder3<OutPointEncoder<'e>, ScriptEncoder<'e>, SequenceEncoder<'e>>
1505 );
1506}
1507
1508#[cfg(feature = "encoding")]
1509impl encoding::Encode for TxIn {
1510 type Encoder<'e> = Encoder3<OutPointEncoder<'e>, ScriptEncoder<'e>, SequenceEncoder<'e>>;
1511
1512 fn encoder(&self) -> Self::Encoder<'_> {
1513 Encoder3::new(
1514 self.previous_output.encoder(),
1515 self.script_sig.encoder(),
1516 self.sequence.encoder(),
1517 )
1518 }
1519}
1520
1521#[cfg(feature = "encoding")]
1523#[derive(Debug, Clone)]
1524pub struct WitnessesEncoder<'e> {
1525 inputs: &'e [TxIn],
1526 cur_enc: Option<WitnessEncoder<'e>>,
1528}
1529
1530#[cfg(feature = "encoding")]
1531impl<'e> WitnessesEncoder<'e> {
1532 pub fn new(inputs: &'e [TxIn]) -> Self {
1534 Self { inputs, cur_enc: inputs.first().map(|input| input.witness.encoder()) }
1535 }
1536}
1537
1538#[cfg(feature = "encoding")]
1539impl encoding::Encoder for WitnessesEncoder<'_> {
1540 #[inline]
1541 fn current_chunk(&self) -> &[u8] {
1542 self.cur_enc.as_ref().map(WitnessEncoder::current_chunk).unwrap_or_default()
1543 }
1544
1545 #[inline]
1546 fn advance(&mut self) -> EncoderStatus {
1547 let Some(cur) = self.cur_enc.as_mut() else {
1548 return EncoderStatus::Finished;
1549 };
1550
1551 loop {
1552 if cur.advance().has_more() {
1555 return EncoderStatus::HasMore;
1556 }
1557 self.inputs = &self.inputs[1..];
1559
1560 if let Some(input) = self.inputs.first() {
1562 *cur = input.witness.encoder();
1563 if !cur.current_chunk().is_empty() {
1564 return EncoderStatus::HasMore;
1565 }
1566 } else {
1567 self.cur_enc = None; return EncoderStatus::Finished;
1569 }
1570 }
1571 }
1572}
1573
1574#[cfg(feature = "encoding")]
1575type TxInInnerDecoder = Decoder3<OutPointDecoder, ScriptBufDecoder, SequenceDecoder>;
1576
1577#[cfg(feature = "encoding")]
1578crate::decoder_newtype! {
1579 #[derive(Debug, Clone)]
1581 pub struct TxInDecoder(TxInInnerDecoder);
1582
1583 pub const fn new() -> Self {
1585 Self(Decoder3::new(
1586 OutPointDecoder::new(),
1587 ScriptBufDecoder::new(),
1588 SequenceDecoder::new(),
1589 ))
1590 }
1591
1592 fn end(
1593 result: Result<<TxInInnerDecoder as encoding::Decoder>::Output, <TxInInnerDecoder as encoding::Decoder>::Error>
1594 ) -> Result<TxIn, TxInDecoderError> {
1595 let (previous_output, script_sig, sequence) = result.map_err(TxInDecoderError)?;
1596 Ok(TxIn { previous_output, script_sig, sequence, witness: Witness::default() })
1597 }
1598}
1599
1600#[cfg(feature = "encoding")]
1601impl encoding::Decode for TxIn {
1602 type Decoder = TxInDecoder;
1603}
1604
1605#[cfg(feature = "encoding")]
1607#[derive(Debug, Clone, PartialEq, Eq)]
1608pub struct TxInDecoderError(pub(super) <TxInInnerDecoder as encoding::Decoder>::Error);
1609
1610#[cfg(feature = "encoding")]
1611impl From<Infallible> for TxInDecoderError {
1612 fn from(never: Infallible) -> Self { match never {} }
1613}
1614
1615#[cfg(feature = "encoding")]
1616impl fmt::Display for TxInDecoderError {
1617 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1618 write_err!(f, "txin decoder error"; self.0)
1619 }
1620}
1621
1622#[cfg(all(feature = "encoding", feature = "std"))]
1623impl std::error::Error for TxInDecoderError {
1624 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
1625}
1626
1627impl Encodable for Sequence {
1628 fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
1629 self.0.consensus_encode(w)
1630 }
1631}
1632
1633impl Decodable for Sequence {
1634 fn consensus_decode<R: Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
1635 Decodable::consensus_decode(r).map(Sequence)
1636 }
1637}
1638
1639impl Encodable for Transaction {
1640 fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
1641 let mut len = 0;
1642 len += self.version.consensus_encode(w)?;
1643
1644 if !self.uses_segwit_serialization() {
1646 len += self.input.consensus_encode(w)?;
1647 len += self.output.consensus_encode(w)?;
1648 } else {
1649 len += SEGWIT_MARKER.consensus_encode(w)?;
1651 len += SEGWIT_FLAG.consensus_encode(w)?;
1652 len += self.input.consensus_encode(w)?;
1653 len += self.output.consensus_encode(w)?;
1654 for input in &self.input {
1655 len += input.witness.consensus_encode(w)?;
1656 }
1657 }
1658 len += self.lock_time.consensus_encode(w)?;
1659 Ok(len)
1660 }
1661}
1662
1663impl Decodable for Transaction {
1664 fn consensus_decode_from_finite_reader<R: Read + ?Sized>(
1665 r: &mut R,
1666 ) -> Result<Self, encode::Error> {
1667 let version = Version::consensus_decode_from_finite_reader(r)?;
1668 let input = Vec::<TxIn>::consensus_decode_from_finite_reader(r)?;
1669 if input.is_empty() {
1671 let segwit_flag = u8::consensus_decode_from_finite_reader(r)?;
1672 match segwit_flag {
1673 1 => {
1675 let mut input = Vec::<TxIn>::consensus_decode_from_finite_reader(r)?;
1676 let output = Vec::<TxOut>::consensus_decode_from_finite_reader(r)?;
1677 for txin in input.iter_mut() {
1678 txin.witness = Decodable::consensus_decode_from_finite_reader(r)?;
1679 }
1680 if !input.is_empty() && input.iter().all(|input| input.witness.is_empty()) {
1681 Err(encode::Error::ParseFailed("witness flag set but no witnesses present"))
1682 } else {
1683 Ok(Transaction {
1684 version,
1685 input,
1686 output,
1687 lock_time: Decodable::consensus_decode_from_finite_reader(r)?,
1688 })
1689 }
1690 }
1691 x => Err(encode::Error::UnsupportedSegwitFlag(x)),
1693 }
1694 } else {
1696 Ok(Transaction {
1697 version,
1698 input,
1699 output: Decodable::consensus_decode_from_finite_reader(r)?,
1700 lock_time: Decodable::consensus_decode_from_finite_reader(r)?,
1701 })
1702 }
1703 }
1704}
1705
1706#[cfg(feature = "encoding")]
1707impl encoding::Encode for Transaction {
1708 type Encoder<'e> = TransactionEncoder<'e>;
1709
1710 fn encoder(&self) -> Self::Encoder<'_> {
1711 let version = self.version.encoder();
1712 let inputs = Encoder2::new(
1713 CompactSizeEncoder::new(self.input.len()),
1714 SliceEncoder::without_length_prefix(self.input.as_ref()),
1715 );
1716 let outputs = Encoder2::new(
1717 CompactSizeEncoder::new(self.output.len()),
1718 SliceEncoder::without_length_prefix(self.output.as_ref()),
1719 );
1720 let lock_time = self.lock_time.encoder();
1721
1722 if self.uses_segwit_serialization() {
1723 let segwit = ArrayEncoder::without_length_prefix([0x00, 0x01]);
1724 let witnesses = WitnessesEncoder::new(self.input.as_slice());
1725 TransactionEncoder::new(Encoder6::new(
1726 version,
1727 Some(segwit),
1728 inputs,
1729 outputs,
1730 Some(witnesses),
1731 lock_time,
1732 ))
1733 } else {
1734 TransactionEncoder::new(Encoder6::new(version, None, inputs, outputs, None, lock_time))
1735 }
1736 }
1737}
1738
1739#[cfg(feature = "encoding")]
1740impl encoding::Decode for Transaction {
1741 type Decoder = TransactionDecoder;
1742}
1743
1744#[cfg(feature = "encoding")]
1745type TransactionEncoderInner<'e> = Encoder6<
1746 VersionEncoder<'e>,
1747 Option<ArrayEncoder<2>>,
1748 Encoder2<CompactSizeEncoder, SliceEncoder<'e, TxIn>>,
1749 Encoder2<CompactSizeEncoder, SliceEncoder<'e, TxOut>>,
1750 Option<WitnessesEncoder<'e>>,
1751 LockTimeEncoder<'e>,
1752>;
1753
1754#[cfg(feature = "encoding")]
1755encoding::encoder_newtype! {
1756 #[derive(Debug, Clone)]
1758 pub struct TransactionEncoder<'e>(TransactionEncoderInner<'e>);
1759}
1760
1761#[cfg(feature = "encoding")]
1763#[derive(Debug, Clone)]
1764pub struct TransactionDecoder {
1765 state: TransactionDecoderState,
1766}
1767
1768#[cfg(feature = "encoding")]
1769impl TransactionDecoder {
1770 pub const fn new() -> Self {
1772 Self { state: TransactionDecoderState::Version(VersionDecoder::new()) }
1773 }
1774}
1775
1776#[cfg(feature = "encoding")]
1777impl Default for TransactionDecoder {
1778 fn default() -> Self { Self::new() }
1779}
1780
1781#[cfg(feature = "encoding")]
1782#[allow(clippy::too_many_lines)]
1783impl encoding::Decoder for TransactionDecoder {
1784 type Output = Transaction;
1785 type Error = TransactionDecoderError;
1786
1787 #[inline]
1788 fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<DecoderStatus, Self::Error> {
1789 use TransactionDecoderError as E;
1790 use TransactionDecoderErrorInner as Inner;
1791 use TransactionDecoderState as State;
1792
1793 loop {
1794 match &mut self.state {
1796 State::Version(decoder) => {
1797 if decoder.push_bytes(bytes).map_err(|e| E(Inner::Version(e)))?.needs_more() {
1798 return Ok(DecoderStatus::NeedsMore);
1800 }
1801 }
1802 State::Inputs(_, _, decoder) =>
1803 if decoder.push_bytes(bytes).map_err(|e| E(Inner::Inputs(e)))?.needs_more() {
1804 return Ok(DecoderStatus::NeedsMore);
1805 },
1806 State::SegwitFlag(_) =>
1807 if bytes.is_empty() {
1808 return Ok(DecoderStatus::NeedsMore);
1809 },
1810 State::Outputs(_, _, _, decoder) =>
1811 if decoder.push_bytes(bytes).map_err(|e| E(Inner::Outputs(e)))?.needs_more() {
1812 return Ok(DecoderStatus::NeedsMore);
1813 },
1814 State::Witnesses(_, _, _, _, decoder) =>
1815 if decoder.push_bytes(bytes).map_err(|e| E(Inner::Witness(e)))?.needs_more() {
1816 return Ok(DecoderStatus::NeedsMore);
1817 },
1818 State::LockTime(_, _, _, decoder) =>
1819 if decoder.push_bytes(bytes).map_err(|e| E(Inner::LockTime(e)))?.needs_more() {
1820 return Ok(DecoderStatus::NeedsMore);
1821 },
1822 State::Done(..) => return Ok(DecoderStatus::Ready),
1823 State::Errored => panic!("call to push_bytes() after decoder errored"),
1824 }
1825
1826 match mem::replace(&mut self.state, State::Errored) {
1828 State::Version(decoder) => {
1829 let version = decoder.end().map_err(|e| E(Inner::Version(e)))?;
1830 self.state = State::Inputs(version, Attempt::First, VecDecoder::<TxIn>::new());
1831 }
1832 State::Inputs(version, attempt, decoder) => {
1833 let inputs = decoder.end().map_err(|e| E(Inner::Inputs(e)))?;
1834
1835 if Attempt::First == attempt {
1836 if inputs.is_empty() {
1837 self.state = State::SegwitFlag(version);
1838 } else {
1839 self.state = State::Outputs(
1840 version,
1841 inputs,
1842 IsSegwit::No,
1843 VecDecoder::<TxOut>::new(),
1844 );
1845 }
1846 } else {
1847 self.state = State::Outputs(
1848 version,
1849 inputs,
1850 IsSegwit::Yes,
1851 VecDecoder::<TxOut>::new(),
1852 );
1853 }
1854 }
1855 State::SegwitFlag(version) => {
1856 let segwit_flag = bytes[0];
1857 *bytes = &bytes[1..];
1858
1859 if segwit_flag != 1 {
1860 return Err(E(Inner::UnsupportedSegwitFlag(segwit_flag)));
1861 }
1862 self.state = State::Inputs(version, Attempt::Second, VecDecoder::<TxIn>::new());
1863 }
1864 State::Outputs(version, inputs, is_segwit, decoder) => {
1865 let outputs = decoder.end().map_err(|e| E(Inner::Outputs(e)))?;
1866 if is_segwit == IsSegwit::Yes && !inputs.is_empty() {
1868 self.state = State::Witnesses(
1869 version,
1870 inputs,
1871 outputs,
1872 Iteration(0),
1873 WitnessDecoder::new(),
1874 );
1875 } else {
1876 self.state =
1877 State::LockTime(version, inputs, outputs, LockTimeDecoder::new());
1878 }
1879 }
1880 State::Witnesses(version, mut inputs, outputs, iteration, decoder) => {
1881 let iteration = iteration.0;
1882
1883 inputs[iteration].witness = decoder.end().map_err(|e| E(Inner::Witness(e)))?;
1884 if iteration < inputs.len() - 1 {
1885 self.state = State::Witnesses(
1886 version,
1887 inputs,
1888 outputs,
1889 Iteration(iteration + 1),
1890 WitnessDecoder::new(),
1891 );
1892 } else {
1893 if !inputs.is_empty() && inputs.iter().all(|input| input.witness.is_empty())
1894 {
1895 return Err(E(Inner::NoWitnesses));
1896 }
1897 self.state =
1898 State::LockTime(version, inputs, outputs, LockTimeDecoder::new());
1899 }
1900 }
1901 State::LockTime(version, inputs, outputs, decoder) => {
1902 let lock_time = decoder.end().map_err(|e| E(Inner::LockTime(e)))?;
1903 self.state = State::Done(Transaction {
1904 version,
1905 lock_time,
1906 input: inputs,
1907 output: outputs,
1908 });
1909 return Ok(DecoderStatus::Ready);
1910 }
1911 State::Done(..) => return Ok(DecoderStatus::Ready),
1912 State::Errored => unreachable!("checked above"),
1913 }
1914 }
1915 }
1916
1917 #[inline]
1918 fn end(self) -> Result<Self::Output, Self::Error> {
1919 use TransactionDecoderError as E;
1920 use TransactionDecoderErrorInner as Inner;
1921 use TransactionDecoderState as State;
1922
1923 match self.state {
1924 State::Version(_) => Err(E(Inner::EarlyEnd("version"))),
1925 State::Inputs(..) => Err(E(Inner::EarlyEnd("inputs"))),
1926 State::SegwitFlag(..) => Err(E(Inner::EarlyEnd("segwit flag"))),
1927 State::Outputs(..) => Err(E(Inner::EarlyEnd("outputs"))),
1928 State::Witnesses(..) => Err(E(Inner::EarlyEnd("witnesses"))),
1929 State::LockTime(..) => Err(E(Inner::EarlyEnd("locktime"))),
1930 State::Done(tx) => {
1931 if tx.output.is_empty() {
1933 return Err(E(Inner::NoOutputs));
1934 }
1935 if tx.input.len() > 1 {
1937 for (index, input) in tx.input.iter().enumerate() {
1938 if input.previous_output == OutPoint::null() {
1939 return Err(E(Inner::NullPrevoutInNonCoinbase(index)));
1940 }
1941 }
1942 }
1943 if tx.is_coinbase() {
1945 let len = tx.input[0].script_sig.len();
1946 if len < 2 {
1947 return Err(E(Inner::CoinbaseScriptSigTooSmall(len)));
1948 }
1949 if len > 100 {
1950 return Err(E(Inner::CoinbaseScriptSigTooLarge(len)));
1951 }
1952 }
1953 let mut outpoints: Vec<_> = tx.input.iter().map(|i| i.previous_output).collect();
1955 outpoints.sort_unstable();
1956 for pair in outpoints.windows(2) {
1957 if pair[0] == pair[1] {
1958 return Err(E(Inner::DuplicateInput(pair[0])));
1959 }
1960 }
1961 let mut total_out: u64 = 0;
1965 for output in &tx.output {
1966 total_out = total_out.saturating_add(output.value.to_sat());
1967 if total_out > Amount::MAX_MONEY.to_sat() {
1968 return Err(E(Inner::OutputValueSumTooLarge(total_out)));
1969 }
1970 }
1971 Ok(tx)
1972 }
1973 State::Errored => panic!("call to end() after decoder errored"),
1974 }
1975 }
1976
1977 #[inline]
1978 fn read_limit(&self) -> usize {
1979 use TransactionDecoderState as State;
1980
1981 match &self.state {
1982 State::Version(decoder) => decoder.read_limit(),
1983 State::Inputs(_, _, decoder) => decoder.read_limit(),
1984 State::SegwitFlag(_) => 1,
1985 State::Outputs(_, _, _, decoder) => decoder.read_limit(),
1986 State::Witnesses(_, _, _, _, decoder) => decoder.read_limit(),
1987 State::LockTime(_, _, _, decoder) => decoder.read_limit(),
1988 State::Done(_) => 0,
1989 State::Errored => 0,
1992 }
1993 }
1994}
1995
1996#[cfg(feature = "encoding")]
1998#[derive(Debug, Clone)]
1999enum TransactionDecoderState {
2000 Version(VersionDecoder),
2002 Inputs(Version, Attempt, VecDecoder<TxIn>),
2004 SegwitFlag(Version),
2006 Outputs(Version, Vec<TxIn>, IsSegwit, VecDecoder<TxOut>),
2008 Witnesses(Version, Vec<TxIn>, Vec<TxOut>, Iteration, WitnessDecoder),
2010 LockTime(Version, Vec<TxIn>, Vec<TxOut>, LockTimeDecoder),
2012 Done(Transaction),
2014 Errored,
2017}
2018
2019#[cfg(feature = "encoding")]
2021#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2022enum Attempt {
2023 First,
2025 Second,
2027}
2028
2029#[cfg(feature = "encoding")]
2031#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2032enum IsSegwit {
2033 Yes,
2035 No,
2037}
2038
2039#[cfg(feature = "encoding")]
2041#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2042struct Iteration(usize);
2043
2044#[cfg(feature = "encoding")]
2046#[derive(Debug, Clone, PartialEq, Eq)]
2047pub struct TransactionDecoderError(pub(crate) TransactionDecoderErrorInner);
2048
2049#[cfg(feature = "encoding")]
2050#[derive(Debug, Clone, PartialEq, Eq)]
2051pub(crate) enum TransactionDecoderErrorInner {
2052 Version(VersionDecoderError),
2054 UnsupportedSegwitFlag(u8),
2056 Inputs(encoding::VecDecoderError<TxInDecoderError>),
2058 Outputs(encoding::VecDecoderError<TxOutDecoderError>),
2060 Witness(WitnessDecoderError),
2062 NoWitnesses,
2064 LockTime(LockTimeDecoderError),
2066 EarlyEnd(&'static str),
2069 NullPrevoutInNonCoinbase(usize),
2071 CoinbaseScriptSigTooSmall(usize),
2073 CoinbaseScriptSigTooLarge(usize),
2075 DuplicateInput(OutPoint),
2077 OutputValueSumTooLarge(u64),
2079 NoOutputs,
2081}
2082
2083#[cfg(feature = "encoding")]
2084impl From<Infallible> for TransactionDecoderError {
2085 fn from(never: Infallible) -> Self { match never {} }
2086}
2087
2088#[cfg(feature = "encoding")]
2089impl fmt::Display for TransactionDecoderError {
2090 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2091 use TransactionDecoderErrorInner as E;
2092
2093 match self.0 {
2094 E::Version(ref e) => write_err!(f, "transaction decoder error"; e),
2095 E::UnsupportedSegwitFlag(v) => {
2096 write!(f, "we only support segwit flag value 0x01: {}", v)
2097 }
2098 E::Inputs(ref e) => write_err!(f, "transaction decoder error"; e),
2099 E::Outputs(ref e) => write_err!(f, "transaction decoder error"; e),
2100 E::Witness(ref e) => write_err!(f, "transaction decoder error"; e),
2101 E::NoWitnesses => write!(f, "non-empty Segwit transaction with no witnesses"),
2102 E::LockTime(ref e) => write_err!(f, "transaction decoder error"; e),
2103 E::EarlyEnd(s) => write!(f, "early end of transaction (still decoding {})", s),
2104 E::NullPrevoutInNonCoinbase(index) =>
2105 write!(f, "null prevout in non-coinbase transaction at input {}", index),
2106 E::CoinbaseScriptSigTooSmall(len) =>
2107 write!(f, "coinbase scriptSig too small: {} bytes (min 2)", len),
2108 E::CoinbaseScriptSigTooLarge(len) =>
2109 write!(f, "coinbase scriptSig too large: {} bytes (max 100)", len),
2110 E::DuplicateInput(ref outpoint) =>
2111 write!(f, "duplicate input: {:?}:{}", outpoint.txid, outpoint.vout),
2112 E::OutputValueSumTooLarge(val) =>
2113 write!(f, "sum of output values {} satoshis exceeds MAX_MONEY", val),
2114 E::NoOutputs => write!(f, "transaction has no outputs"),
2115 }
2116 }
2117}
2118
2119#[cfg(all(feature = "encoding", feature = "std"))]
2120impl std::error::Error for TransactionDecoderError {
2121 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
2122 use TransactionDecoderErrorInner as E;
2123
2124 match self.0 {
2125 E::Version(ref e) => Some(e),
2126 E::UnsupportedSegwitFlag(_) => None,
2127 E::Inputs(ref e) => Some(e),
2128 E::Outputs(ref e) => Some(e),
2129 E::Witness(ref e) => Some(e),
2130 E::NoWitnesses => None,
2131 E::LockTime(ref e) => Some(e),
2132 E::EarlyEnd(_) => None,
2133 E::NullPrevoutInNonCoinbase(_) => None,
2134 E::CoinbaseScriptSigTooSmall(_) => None,
2135 E::CoinbaseScriptSigTooLarge(_) => None,
2136 E::DuplicateInput(_) => None,
2137 E::OutputValueSumTooLarge(_) => None,
2138 E::NoOutputs => None,
2139 }
2140 }
2141}
2142
2143impl From<Transaction> for Txid {
2144 fn from(tx: Transaction) -> Txid { tx.compute_txid() }
2145}
2146
2147impl From<&Transaction> for Txid {
2148 fn from(tx: &Transaction) -> Txid { tx.compute_txid() }
2149}
2150
2151impl From<Transaction> for Wtxid {
2152 fn from(tx: Transaction) -> Wtxid { tx.compute_wtxid() }
2153}
2154
2155impl From<&Transaction> for Wtxid {
2156 fn from(tx: &Transaction) -> Wtxid { tx.compute_wtxid() }
2157}
2158
2159pub fn effective_value(
2173 fee_rate: FeeRate,
2174 satisfaction_weight: Weight,
2175 value: Amount,
2176) -> Option<SignedAmount> {
2177 let weight = satisfaction_weight.checked_add(TxIn::BASE_WEIGHT)?;
2178 let signed_input_fee = fee_rate.checked_mul_by_weight(weight)?.to_signed().ok()?;
2179 value.to_signed().ok()?.checked_sub(signed_input_fee)
2180}
2181
2182pub fn predict_weight<I, O>(inputs: I, output_script_lens: O) -> Weight
2226where
2227 I: IntoIterator<Item = InputWeightPrediction>,
2228 O: IntoIterator<Item = usize>,
2229{
2230 let (input_count, partial_input_weight, inputs_with_witnesses) = inputs.into_iter().fold(
2238 (0, 0, 0),
2239 |(count, partial_input_weight, inputs_with_witnesses), prediction| {
2240 (
2241 count + 1,
2242 partial_input_weight + prediction.weight().to_wu() as usize,
2243 inputs_with_witnesses + (prediction.witness_size > 0) as usize,
2244 )
2245 },
2246 );
2247
2248 let (output_count, output_scripts_size) = output_script_lens.into_iter().fold(
2253 (0, 0),
2254 |(output_count, total_scripts_size), script_len| {
2255 let script_size = script_len + VarInt(script_len as u64).size();
2256 (output_count + 1, total_scripts_size + script_size)
2257 },
2258 );
2259 predict_weight_internal(
2260 input_count,
2261 partial_input_weight,
2262 inputs_with_witnesses,
2263 output_count,
2264 output_scripts_size,
2265 )
2266}
2267
2268const fn predict_weight_internal(
2269 input_count: usize,
2270 partial_input_weight: usize,
2271 inputs_with_witnesses: usize,
2272 output_count: usize,
2273 output_scripts_size: usize,
2274) -> Weight {
2275 let input_weight = partial_input_weight + input_count * 4 * (32 + 4 + 4);
2278
2279 let output_size = 8 * output_count + output_scripts_size;
2281 let non_input_size =
2282 4 +
2284 VarInt(input_count as u64).size() +
2286 VarInt(output_count as u64).size() +
2287 output_size +
2288 4;
2290 let weight = if inputs_with_witnesses == 0 {
2291 non_input_size * 4 + input_weight
2292 } else {
2293 non_input_size * 4 + input_weight + input_count - inputs_with_witnesses + 2
2294 };
2295 Weight::from_wu(weight as u64)
2296}
2297
2298pub const fn predict_weight_from_slices(
2306 inputs: &[InputWeightPrediction],
2307 output_script_lens: &[usize],
2308) -> Weight {
2309 let mut partial_input_weight = 0;
2310 let mut inputs_with_witnesses = 0;
2311
2312 let mut i = 0;
2314 while i < inputs.len() {
2315 let prediction = inputs[i];
2316 partial_input_weight += prediction.weight().to_wu() as usize;
2317 inputs_with_witnesses += (prediction.witness_size > 0) as usize;
2318 i += 1;
2319 }
2320
2321 let mut output_scripts_size = 0;
2322
2323 i = 0;
2324 while i < output_script_lens.len() {
2325 let script_len = output_script_lens[i];
2326 output_scripts_size += script_len + VarInt(script_len as u64).size();
2327 i += 1;
2328 }
2329
2330 predict_weight_internal(
2331 inputs.len(),
2332 partial_input_weight,
2333 inputs_with_witnesses,
2334 output_script_lens.len(),
2335 output_scripts_size,
2336 )
2337}
2338
2339#[derive(Copy, Clone, Debug)]
2345pub struct InputWeightPrediction {
2346 script_size: usize,
2347 witness_size: usize,
2348}
2349
2350impl InputWeightPrediction {
2351 pub const P2WPKH_MAX: Self = InputWeightPrediction::from_slice(0, &[72, 33]);
2362
2363 pub const P2PKH_COMPRESSED_MAX: Self = InputWeightPrediction::from_slice(107, &[]);
2375
2376 pub const P2PKH_UNCOMPRESSED_MAX: Self = InputWeightPrediction::from_slice(139, &[]);
2382
2383 pub const P2TR_KEY_DEFAULT_SIGHASH: Self = InputWeightPrediction::from_slice(0, &[64]);
2389
2390 pub const P2TR_KEY_NON_DEFAULT_SIGHASH: Self = InputWeightPrediction::from_slice(0, &[65]);
2396
2397 pub const fn ground_p2wpkh(bytes_to_grind: usize) -> Self {
2412 let der_signature_size = 10 + (62 - bytes_to_grind);
2414 InputWeightPrediction::from_slice(0, &[der_signature_size, 33])
2415 }
2416
2417 pub const fn ground_p2pkh_compressed(bytes_to_grind: usize) -> Self {
2432 let der_signature_size = 10 + (62 - bytes_to_grind);
2434
2435 InputWeightPrediction::from_slice(2 + 33 + der_signature_size, &[])
2436 }
2437
2438 pub fn new<T>(input_script_len: usize, witness_element_lengths: T) -> Self
2440 where
2441 T: IntoIterator,
2442 T::Item: Borrow<usize>,
2443 {
2444 let (count, total_size) =
2445 witness_element_lengths.into_iter().fold((0, 0), |(count, total_size), elem_len| {
2446 let elem_len = *elem_len.borrow();
2447 let elem_size = elem_len + VarInt(elem_len as u64).size();
2448 (count + 1, total_size + elem_size)
2449 });
2450 let witness_size = if count > 0 { total_size + VarInt(count as u64).size() } else { 0 };
2451 let script_size = input_script_len + VarInt(input_script_len as u64).size();
2452
2453 InputWeightPrediction { script_size, witness_size }
2454 }
2455
2456 pub const fn from_slice(input_script_len: usize, witness_element_lengths: &[usize]) -> Self {
2462 let mut i = 0;
2463 let mut total_size = 0;
2464 while i < witness_element_lengths.len() {
2466 let elem_len = witness_element_lengths[i];
2467 let elem_size = elem_len + VarInt(elem_len as u64).size();
2468 total_size += elem_size;
2469 i += 1;
2470 }
2471 let witness_size = if !witness_element_lengths.is_empty() {
2472 total_size + VarInt(witness_element_lengths.len() as u64).size()
2473 } else {
2474 0
2475 };
2476 let script_size = input_script_len + VarInt(input_script_len as u64).size();
2477
2478 InputWeightPrediction { script_size, witness_size }
2479 }
2480
2481 pub const fn weight(&self) -> Weight {
2484 Weight::from_wu_usize(self.script_size * 4 + self.witness_size)
2485 }
2486}
2487
2488#[cfg(feature = "arbitrary")]
2489impl<'a> Arbitrary<'a> for InputWeightPrediction {
2490 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
2491 let max_block = Weight::MAX_BLOCK.to_wu() as usize;
2493 let input_script_len = u.int_in_range(0..=max_block)?;
2494 let remaining = max_block - input_script_len;
2495
2496 let mut witness_length = u.int_in_range(0..=remaining)?;
2498 let mut witness_element_lengths = Vec::new();
2499
2500 while witness_length > 0 {
2502 let elem = u.int_in_range(1..=witness_length)?;
2503 witness_element_lengths.push(elem);
2504 witness_length -= elem;
2505 }
2506
2507 match u.int_in_range(0..=6)? {
2508 0 => Ok(InputWeightPrediction::P2WPKH_MAX),
2509 1 => Ok(InputWeightPrediction::P2PKH_COMPRESSED_MAX),
2510 2 => Ok(InputWeightPrediction::P2PKH_UNCOMPRESSED_MAX),
2511 3 => Ok(InputWeightPrediction::P2TR_KEY_DEFAULT_SIGHASH),
2512 4 => Ok(InputWeightPrediction::P2TR_KEY_NON_DEFAULT_SIGHASH),
2513 5 => Ok(InputWeightPrediction::new(input_script_len, witness_element_lengths)),
2514 _ => Ok(InputWeightPrediction::from_slice(input_script_len, &witness_element_lengths)),
2515 }
2516 }
2517}
2518
2519#[cfg(feature = "arbitrary")]
2520impl<'a> Arbitrary<'a> for OutPoint {
2521 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
2522 Ok(OutPoint { txid: Txid::arbitrary(u)?, vout: u32::arbitrary(u)? })
2523 }
2524}
2525
2526#[cfg(feature = "arbitrary")]
2527impl<'a> Arbitrary<'a> for Sequence {
2528 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
2529 let choice_range = 8;
2530
2531 let choice = u.int_in_range(0..=choice_range)?;
2533 match choice {
2534 0 => Ok(Sequence::MAX),
2535 1 => Ok(Sequence::ZERO),
2536 2 => Ok(Sequence::MIN_NO_RBF),
2537 3 => Ok(Sequence::ENABLE_RBF_NO_LOCKTIME),
2538 4 => Ok(Sequence::from_consensus(relative::Height::MIN.to_consensus_u32())),
2539 5 => Ok(Sequence::from_consensus(relative::Height::MAX.to_consensus_u32())),
2540 6 => Ok(Sequence::from_consensus(relative::Time::MIN.to_consensus_u32())),
2541 7 => Ok(Sequence::from_consensus(relative::Time::MAX.to_consensus_u32())),
2542 _ => Ok(Sequence(u.arbitrary()?)),
2543 }
2544 }
2545}
2546
2547#[cfg(feature = "arbitrary")]
2548impl<'a> Arbitrary<'a> for Transaction {
2549 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
2550 use absolute::LockTime;
2551
2552 Ok(Transaction {
2553 version: Version::arbitrary(u)?,
2554 lock_time: LockTime::arbitrary(u)?,
2555 input: Vec::<TxIn>::arbitrary(u)?,
2556 output: Vec::<TxOut>::arbitrary(u)?,
2557 })
2558 }
2559}
2560
2561#[cfg(feature = "arbitrary")]
2562impl<'a> Arbitrary<'a> for TxIn {
2563 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
2564 Ok(TxIn {
2565 previous_output: OutPoint::arbitrary(u)?,
2566 script_sig: ScriptBuf::arbitrary(u)?,
2567 sequence: Sequence::arbitrary(u)?,
2568 witness: Witness::arbitrary(u)?,
2569 })
2570 }
2571}
2572
2573#[cfg(feature = "arbitrary")]
2574impl<'a> Arbitrary<'a> for Txid {
2575 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
2576 let arbitrary_bytes = u.arbitrary()?;
2577 let t = sha256d::Hash::from_byte_array(arbitrary_bytes);
2578 Ok(Txid(t))
2579 }
2580}
2581
2582#[cfg(feature = "arbitrary")]
2583impl<'a> Arbitrary<'a> for TxOut {
2584 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
2585 Ok(TxOut { value: Amount::arbitrary(u)?, script_pubkey: ScriptBuf::arbitrary(u)? })
2586 }
2587}
2588
2589#[cfg(feature = "arbitrary")]
2590impl<'a> Arbitrary<'a> for Version {
2591 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
2592 let choice = u.int_in_range(0..=2)?;
2594 match choice {
2595 0 => Ok(Version::ONE),
2596 1 => Ok(Version::TWO),
2597 _ => Ok(Version(u.arbitrary()?)),
2598 }
2599 }
2600}
2601
2602#[cfg(feature = "arbitrary")]
2603impl<'a> Arbitrary<'a> for Wtxid {
2604 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
2605 Ok(Wtxid::from_byte_array(u.arbitrary()?))
2606 }
2607}
2608
2609#[cfg(test)]
2610mod tests {
2611 use core::str::FromStr;
2612
2613 use hex::{test_hex_unwrap as hex, FromHex};
2614
2615 use super::*;
2616 use crate::blockdata::constants::WITNESS_SCALE_FACTOR;
2617 use crate::consensus::encode::{deserialize, serialize};
2618 use crate::sighash::EcdsaSighashType;
2619
2620 const SOME_TX: &str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
2621
2622 #[test]
2623 fn encode_to_unsized_writer() {
2624 let mut buf = [0u8; 1024];
2625 let raw_tx = hex!(SOME_TX);
2626 let tx: Transaction = Decodable::consensus_decode(&mut raw_tx.as_slice()).unwrap();
2627
2628 let size = tx.consensus_encode(&mut &mut buf[..]).unwrap();
2629 assert_eq!(size, SOME_TX.len() / 2);
2630 assert_eq!(raw_tx, &buf[..size]);
2631 }
2632
2633 #[test]
2634 fn outpoint() {
2635 assert_eq!(OutPoint::from_str("i don't care"), Err(ParseOutPointError::Format));
2636 assert_eq!(
2637 OutPoint::from_str(
2638 "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:1:1"
2639 ),
2640 Err(ParseOutPointError::Format)
2641 );
2642 assert_eq!(
2643 OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:"),
2644 Err(ParseOutPointError::Format)
2645 );
2646 assert_eq!(
2647 OutPoint::from_str(
2648 "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:11111111111"
2649 ),
2650 Err(ParseOutPointError::TooLong)
2651 );
2652 assert_eq!(
2653 OutPoint::from_str(
2654 "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:01"
2655 ),
2656 Err(ParseOutPointError::VoutNotCanonical)
2657 );
2658 assert_eq!(
2659 OutPoint::from_str(
2660 "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:+42"
2661 ),
2662 Err(ParseOutPointError::VoutNotCanonical)
2663 );
2664 assert_eq!(
2665 OutPoint::from_str("i don't care:1"),
2666 Err(ParseOutPointError::Txid("i don't care".parse::<Txid>().unwrap_err()))
2667 );
2668 assert_eq!(
2669 OutPoint::from_str(
2670 "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X:1"
2671 ),
2672 Err(ParseOutPointError::Txid(
2673 "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X"
2674 .parse::<Txid>()
2675 .unwrap_err()
2676 ))
2677 );
2678 assert_eq!(
2679 OutPoint::from_str(
2680 "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:lol"
2681 ),
2682 Err(ParseOutPointError::Vout(parse::int::<u32, _>("lol").unwrap_err()))
2683 );
2684
2685 assert_eq!(
2686 OutPoint::from_str(
2687 "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:42"
2688 ),
2689 Ok(OutPoint {
2690 txid: "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456"
2691 .parse()
2692 .unwrap(),
2693 vout: 42,
2694 })
2695 );
2696 assert_eq!(
2697 OutPoint::from_str(
2698 "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0"
2699 ),
2700 Ok(OutPoint {
2701 txid: "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456"
2702 .parse()
2703 .unwrap(),
2704 vout: 0,
2705 })
2706 );
2707 }
2708
2709 #[test]
2710 fn txin() {
2711 let txin: Result<TxIn, _> = deserialize(&hex!("a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff"));
2712 assert!(txin.is_ok());
2713 }
2714
2715 #[test]
2716 fn txin_default() {
2717 let txin = TxIn::default();
2718 assert_eq!(txin.previous_output, OutPoint::default());
2719 assert_eq!(txin.script_sig, ScriptBuf::new());
2720 assert_eq!(txin.sequence, Sequence::from_consensus(0xFFFFFFFF));
2721 assert_eq!(txin.previous_output, OutPoint::default());
2722 assert_eq!(txin.witness.len(), 0);
2723 }
2724
2725 #[test]
2726 fn is_coinbase() {
2727 use crate::blockdata::constants;
2728 use crate::network::Network;
2729
2730 let genesis = constants::genesis_block(Network::Bitcoin);
2731 assert!(genesis.txdata[0].is_coinbase());
2732 let tx_bytes = hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000");
2733 let tx: Transaction = deserialize(&tx_bytes).unwrap();
2734 assert!(!tx.is_coinbase());
2735 }
2736
2737 #[test]
2738 fn nonsegwit_transaction() {
2739 let tx_bytes = hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000");
2740 let tx: Result<Transaction, _> = deserialize(&tx_bytes);
2741 assert!(tx.is_ok());
2742 let realtx = tx.unwrap();
2743 assert_eq!(realtx.version, Version::ONE);
2746 assert_eq!(realtx.input.len(), 1);
2747 assert_eq!(
2750 format!("{:x}", realtx.input[0].previous_output.txid),
2751 "ce9ea9f6f5e422c6a9dbcddb3b9a14d1c78fab9ab520cb281aa2a74a09575da1".to_string()
2752 );
2753 assert_eq!(realtx.input[0].previous_output.vout, 1);
2754 assert_eq!(realtx.output.len(), 1);
2755 assert_eq!(realtx.lock_time, absolute::LockTime::ZERO);
2756
2757 assert_eq!(
2758 format!("{:x}", realtx.compute_txid()),
2759 "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string()
2760 );
2761 assert_eq!(
2762 format!("{:x}", realtx.compute_wtxid()),
2763 "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string()
2764 );
2765 assert_eq!(realtx.weight().to_wu() as usize, tx_bytes.len() * WITNESS_SCALE_FACTOR);
2766 assert_eq!(realtx.total_size(), tx_bytes.len());
2767 assert_eq!(realtx.vsize(), tx_bytes.len());
2768 assert_eq!(realtx.base_size(), tx_bytes.len());
2769 }
2770
2771 #[test]
2772 fn segwit_invalid_transaction() {
2773 let tx_bytes = hex!("0000fd000001021921212121212121212121f8b372b0239cc1dff600000000004f4f4f4f4f4f4f4f000000000000000000000000000000333732343133380d000000000000000000000000000000ff000000000009000dff000000000000000800000000000000000d");
2774 let tx: Result<Transaction, _> = deserialize(&tx_bytes);
2775 assert!(tx.is_err());
2776 assert!(tx.unwrap_err().to_string().contains("witness flag set but no witnesses present"));
2777 }
2778
2779 #[test]
2780 fn segwit_transaction() {
2781 let tx_bytes = hex!(
2782 "02000000000101595895ea20179de87052b4046dfe6fd515860505d6511a9004cf12a1f93cac7c01000000\
2783 00ffffffff01deb807000000000017a9140f3444e271620c736808aa7b33e370bd87cb5a078702483045022\
2784 100fb60dad8df4af2841adc0346638c16d0b8035f5e3f3753b88db122e70c79f9370220756e6633b17fd271\
2785 0e626347d28d60b0a2d6cbb41de51740644b9fb3ba7751040121028fa937ca8cba2197a37c007176ed89410\
2786 55d3bcb8627d085e94553e62f057dcc00000000"
2787 );
2788 let tx: Result<Transaction, _> = deserialize(&tx_bytes);
2789 assert!(tx.is_ok());
2790 let realtx = tx.unwrap();
2791 assert_eq!(realtx.version, Version::TWO);
2794 assert_eq!(realtx.input.len(), 1);
2795 assert_eq!(
2798 format!("{:x}", realtx.input[0].previous_output.txid),
2799 "7cac3cf9a112cf04901a51d605058615d56ffe6d04b45270e89d1720ea955859".to_string()
2800 );
2801 assert_eq!(realtx.input[0].previous_output.vout, 1);
2802 assert_eq!(realtx.output.len(), 1);
2803 assert_eq!(realtx.lock_time, absolute::LockTime::ZERO);
2804
2805 assert_eq!(
2806 format!("{:x}", realtx.compute_txid()),
2807 "f5864806e3565c34d1b41e716f72609d00b55ea5eac5b924c9719a842ef42206".to_string()
2808 );
2809 assert_eq!(
2810 format!("{:x}", realtx.compute_wtxid()),
2811 "80b7d8a82d5d5bf92905b06f2014dd699e03837ca172e3a59d51426ebbe3e7f5".to_string()
2812 );
2813 const EXPECTED_WEIGHT: Weight = Weight::from_wu(442);
2814 assert_eq!(realtx.weight(), EXPECTED_WEIGHT);
2815 assert_eq!(realtx.total_size(), tx_bytes.len());
2816 assert_eq!(realtx.vsize(), 111);
2817
2818 let expected_strippedsize = (442 - realtx.total_size()) / 3;
2819 assert_eq!(realtx.base_size(), expected_strippedsize);
2820
2821 let mut tx_without_witness = realtx;
2823 tx_without_witness.input.iter_mut().for_each(|input| input.witness.clear());
2824 assert_eq!(tx_without_witness.total_size(), tx_without_witness.total_size());
2825 assert_eq!(tx_without_witness.total_size(), expected_strippedsize);
2826 }
2827
2828 #[cfg(feature = "serde")]
2830 #[test]
2831 fn consensus_serde() {
2832 use crate::consensus::serde as con_serde;
2833 let json = "\"010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000\"";
2834 let mut deserializer = serde_json::Deserializer::from_str(json);
2835 let tx =
2836 con_serde::With::<con_serde::Hex>::deserialize::<'_, Transaction, _>(&mut deserializer)
2837 .unwrap();
2838 let tx_bytes = Vec::from_hex(&json[1..(json.len() - 1)]).unwrap();
2839 let expected = deserialize::<Transaction>(&tx_bytes).unwrap();
2840 assert_eq!(tx, expected);
2841 let mut bytes = Vec::new();
2842 let mut serializer = serde_json::Serializer::new(&mut bytes);
2843 con_serde::With::<con_serde::Hex>::serialize(&tx, &mut serializer).unwrap();
2844 assert_eq!(bytes, json.as_bytes())
2845 }
2846
2847 #[test]
2848 fn transaction_version() {
2849 let tx_bytes = hex!("ffffff7f0100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000");
2850 let tx: Result<Transaction, _> = deserialize(&tx_bytes);
2851 assert!(tx.is_ok());
2852 let realtx = tx.unwrap();
2853 assert_eq!(realtx.version, Version::non_standard(2147483647));
2854
2855 let tx2_bytes = hex!("000000800100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000");
2856 let tx2: Result<Transaction, _> = deserialize(&tx2_bytes);
2857 assert!(tx2.is_ok());
2858 let realtx2 = tx2.unwrap();
2859 assert_eq!(realtx2.version, Version::non_standard(-2147483648));
2860 }
2861
2862 #[test]
2863 fn tx_no_input_deserialization() {
2864 let tx_bytes = hex!(
2865 "010000000001000100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"
2866 );
2867 let tx: Transaction = deserialize(&tx_bytes).expect("deserialize tx");
2868
2869 assert_eq!(tx.input.len(), 0);
2870 assert_eq!(tx.output.len(), 1);
2871
2872 let reser = serialize(&tx);
2873 assert_eq!(tx_bytes, reser);
2874 }
2875
2876 #[test]
2877 fn ntxid() {
2878 let tx_bytes = hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000");
2879 let mut tx: Transaction = deserialize(&tx_bytes).unwrap();
2880
2881 let old_ntxid = tx.compute_ntxid();
2882 assert_eq!(
2883 format!("{:x}", old_ntxid),
2884 "c3573dbea28ce24425c59a189391937e00d255150fa973d59d61caf3a06b601d"
2885 );
2886 tx.input[0].script_sig = ScriptBuf::new();
2888 assert_eq!(old_ntxid, tx.compute_ntxid());
2889 tx.output[0].script_pubkey = ScriptBuf::new();
2891 assert!(old_ntxid != tx.compute_ntxid());
2892 }
2893
2894 #[test]
2895 fn txid() {
2896 let tx_bytes = hex!(
2898 "01000000000102ff34f95a672bb6a4f6ff4a7e90fa8c7b3be7e70ffc39bc99be3bda67942e836c00000000\
2899 23220020cde476664d3fa347b8d54ef3aee33dcb686a65ced2b5207cbf4ec5eda6b9b46e4f414d4c934ad8\
2900 1d330314e888888e3bd22c7dde8aac2ca9227b30d7c40093248af7812201000000232200200af6f6a071a6\
2901 9d5417e592ed99d256ddfd8b3b2238ac73f5da1b06fc0b2e79d54f414d4c0ba0c8f505000000001976a914\
2902 dcb5898d9036afad9209e6ff0086772795b1441088ac033c0f000000000017a914889f8c10ff2bd4bb9dab\
2903 b68c5c0d700a46925e6c87033c0f000000000017a914889f8c10ff2bd4bb9dabb68c5c0d700a46925e6c87\
2904 033c0f000000000017a914889f8c10ff2bd4bb9dabb68c5c0d700a46925e6c87033c0f000000000017a914\
2905 889f8c10ff2bd4bb9dabb68c5c0d700a46925e6c87033c0f000000000017a914889f8c10ff2bd4bb9dabb6\
2906 8c5c0d700a46925e6c87033c0f000000000017a914889f8c10ff2bd4bb9dabb68c5c0d700a46925e6c8703\
2907 3c0f000000000017a914889f8c10ff2bd4bb9dabb68c5c0d700a46925e6c87033c0f000000000017a91488\
2908 9f8c10ff2bd4bb9dabb68c5c0d700a46925e6c87033c0f000000000017a914889f8c10ff2bd4bb9dabb68c\
2909 5c0d700a46925e6c87033c0f000000000017a914889f8c10ff2bd4bb9dabb68c5c0d700a46925e6c870500\
2910 47304402200380b8663e727d7e8d773530ef85d5f82c0b067c97ae927800a0876a1f01d8e2022021ee611e\
2911 f6507dfd217add2cd60a8aea3cbcfec034da0bebf3312d19577b8c290147304402207bd9943ce1c2c5547b\
2912 120683fd05d78d23d73be1a5b5a2074ff586b9c853ed4202202881dcf435088d663c9af7b23efb3c03b9db\
2913 c0c899b247aa94a74d9b4b3c84f501483045022100ba12bba745af3f18f6e56be70f8382ca8e107d1ed5ce\
2914 aa3e8c360d5ecf78886f022069b38ebaac8fe6a6b97b497cbbb115f3176f7213540bef08f9292e5a72de52\
2915 de01695321023c9cd9c6950ffee24772be948a45dc5ef1986271e46b686cb52007bac214395a2102756e27\
2916 cb004af05a6e9faed81fd68ff69959e3c64ac8c9f6cd0e08fd0ad0e75d2103fa40da236bd82202a985a910\
2917 4e851080b5940812685769202a3b43e4a8b13e6a53ae050048304502210098b9687b81d725a7970d1eee91\
2918 ff6b89bc9832c2e0e3fb0d10eec143930b006f02206f77ce19dc58ecbfef9221f81daad90bb4f468df3912\
2919 12abc4f084fe2cc9bdef01483045022100e5479f81a3ad564103da5e2ec8e12f61f3ac8d312ab68763c1dd\
2920 d7bae94c20610220789b81b7220b27b681b1b2e87198897376ba9d033bc387f084c8b8310c8539c2014830\
2921 45022100aa1cc48a2d256c0e556616444cc08ae4959d464e5ffff2ae09e3550bdab6ce9f02207192d5e332\
2922 9a56ba7b1ead724634d104f1c3f8749fe6081e6233aee3e855817a016953210260de9cc68658c61af984e3\
2923 ab0281d17cfca1cc035966d335f474932d5e6c5422210355fbb768ce3ce39360277345dbb5f376e706459e\
2924 5a2b5e0e09a535e61690647021023222ceec58b94bd25925dd9743dae6b928737491bd940fc5dd7c6f5d5f\
2925 2adc1e53ae00000000"
2926 );
2927 let tx: Transaction = deserialize(&tx_bytes).unwrap();
2928
2929 assert_eq!(
2930 format!("{:x}", tx.compute_wtxid()),
2931 "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4"
2932 );
2933 assert_eq!(
2934 format!("{:x}", tx.compute_txid()),
2935 "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec"
2936 );
2937 assert_eq!(format!("{:.10x}", tx.compute_txid()), "9652aa62b0");
2938 assert_eq!(tx.weight(), Weight::from_wu(2718));
2939
2940 let tx_bytes = hex!(
2942 "01000000010c7196428403d8b0c88fcb3ee8d64f56f55c8973c9ab7dd106bb4f3527f5888d000000006a47\
2943 30440220503a696f55f2c00eee2ac5e65b17767cd88ed04866b5637d3c1d5d996a70656d02202c9aff698f\
2944 343abb6d176704beda63fcdec503133ea4f6a5216b7f925fa9910c0121024d89b5a13d6521388969209df2\
2945 7a8469bd565aff10e8d42cef931fad5121bfb8ffffffff02b825b404000000001976a914ef79e7ee9fff98\
2946 bcfd08473d2b76b02a48f8c69088ac0000000000000000296a273236303039343836393731373233313237\
2947 3633313032313332353630353838373931323132373000000000"
2948 );
2949 let tx: Transaction = deserialize(&tx_bytes).unwrap();
2950
2951 assert_eq!(
2952 format!("{:x}", tx.compute_wtxid()),
2953 "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"
2954 );
2955 assert_eq!(
2956 format!("{:x}", tx.compute_txid()),
2957 "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"
2958 );
2959 }
2960
2961 #[test]
2962 #[cfg(feature = "serde")]
2963 fn txn_encode_decode() {
2964 let tx_bytes = hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000");
2965 let tx: Transaction = deserialize(&tx_bytes).unwrap();
2966 serde_round_trip!(tx);
2967 }
2968
2969 #[test]
2972 #[cfg(feature = "serde")]
2973 fn segwit_tx_decode() {
2974 let tx_bytes = hex!("010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000");
2975 let tx: Transaction = deserialize(&tx_bytes).unwrap();
2976 assert_eq!(tx.weight(), Weight::from_wu(780));
2977 serde_round_trip!(tx);
2978
2979 let consensus_encoded = serialize(&tx);
2980 assert_eq!(consensus_encoded, tx_bytes);
2981 }
2982
2983 #[test]
2984 fn sighashtype_fromstr_display() {
2985 let sighashtypes = vec![
2986 ("SIGHASH_ALL", EcdsaSighashType::All),
2987 ("SIGHASH_NONE", EcdsaSighashType::None),
2988 ("SIGHASH_SINGLE", EcdsaSighashType::Single),
2989 ("SIGHASH_ALL|SIGHASH_ANYONECANPAY", EcdsaSighashType::AllPlusAnyoneCanPay),
2990 ("SIGHASH_NONE|SIGHASH_ANYONECANPAY", EcdsaSighashType::NonePlusAnyoneCanPay),
2991 ("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", EcdsaSighashType::SinglePlusAnyoneCanPay),
2992 ];
2993 for (s, sht) in sighashtypes {
2994 assert_eq!(sht.to_string(), s);
2995 assert_eq!(EcdsaSighashType::from_str(s).unwrap(), sht);
2996 }
2997 let sht_mistakes = vec![
2998 "SIGHASH_ALL | SIGHASH_ANYONECANPAY",
2999 "SIGHASH_NONE |SIGHASH_ANYONECANPAY",
3000 "SIGHASH_SINGLE| SIGHASH_ANYONECANPAY",
3001 "SIGHASH_ALL SIGHASH_ANYONECANPAY",
3002 "SIGHASH_NONE |",
3003 "SIGHASH_SIGNLE",
3004 "sighash_none",
3005 "Sighash_none",
3006 "SigHash_None",
3007 "SigHash_NONE",
3008 ];
3009 for s in sht_mistakes {
3010 assert_eq!(
3011 EcdsaSighashType::from_str(s).unwrap_err().to_string(),
3012 format!("unrecognized SIGHASH string '{}'", s)
3013 );
3014 }
3015 }
3016
3017 #[test]
3018 fn huge_witness() {
3019 deserialize::<Transaction>(&hex!(include_str!("../../tests/data/huge_witness.hex").trim()))
3020 .unwrap();
3021 }
3022
3023 #[test]
3024 #[cfg(feature = "bitcoinconsensus")]
3025 fn transaction_verify() {
3026 use std::collections::HashMap;
3027
3028 use crate::blockdata::witness::Witness;
3029
3030 let mut spending: Transaction = deserialize(hex!("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700")
3032 .as_slice()).unwrap();
3033 let spent1: Transaction = deserialize(hex!("020000000001040aacd2c49f5f3c0968cfa8caf9d5761436d95385252e3abb4de8f5dcf8a582f20000000017160014bcadb2baea98af0d9a902e53a7e9adff43b191e9feffffff96cd3c93cac3db114aafe753122bd7d1afa5aa4155ae04b3256344ecca69d72001000000171600141d9984579ceb5c67ebfbfb47124f056662fe7adbfeffffffc878dd74d3a44072eae6178bb94b9253177db1a5aaa6d068eb0e4db7631762e20000000017160014df2a48cdc53dae1aba7aa71cb1f9de089d75aac3feffffffe49f99275bc8363f5f593f4eec371c51f62c34ff11cc6d8d778787d340d6896c0100000017160014229b3b297a0587e03375ab4174ef56eeb0968735feffffff03360d0f00000000001976a9149f44b06f6ee92ddbc4686f71afe528c09727a5c788ac24281b00000000001976a9140277b4f68ff20307a2a9f9b4487a38b501eb955888ac227c0000000000001976a9148020cd422f55eef8747a9d418f5441030f7c9c7788ac0247304402204aa3bd9682f9a8e101505f6358aacd1749ecf53a62b8370b97d59243b3d6984f02200384ad449870b0e6e89c92505880411285ecd41cf11e7439b973f13bad97e53901210205b392ffcb83124b1c7ce6dd594688198ef600d34500a7f3552d67947bbe392802473044022033dfd8d190a4ae36b9f60999b217c775b96eb10dee3a1ff50fb6a75325719106022005872e4e36d194e49ced2ebcf8bb9d843d842e7b7e0eb042f4028396088d292f012103c9d7cbf369410b090480de2aa15c6c73d91b9ffa7d88b90724614b70be41e98e0247304402207d952de9e59e4684efed069797e3e2d993e9f98ec8a9ccd599de43005fe3f713022076d190cc93d9513fc061b1ba565afac574e02027c9efbfa1d7b71ab8dbb21e0501210313ad44bc030cc6cb111798c2bf3d2139418d751c1e79ec4e837ce360cc03b97a024730440220029e75edb5e9413eb98d684d62a077b17fa5b7cc19349c1e8cc6c4733b7b7452022048d4b9cae594f03741029ff841e35996ef233701c1ea9aa55c301362ea2e2f68012103590657108a72feb8dc1dec022cf6a230bb23dc7aaa52f4032384853b9f8388baf9d20700")
3034 .as_slice()).unwrap();
3035 let spent2: Transaction = deserialize(hex!("0200000000010166c3d39490dc827a2594c7b17b7d37445e1f4b372179649cd2ce4475e3641bbb0100000017160014e69aa750e9bff1aca1e32e57328b641b611fc817fdffffff01e87c5d010000000017a914f3890da1b99e44cd3d52f7bcea6a1351658ea7be87024830450221009eb97597953dc288de30060ba02d4e91b2bde1af2ecf679c7f5ab5989549aa8002202a98f8c3bd1a5a31c0d72950dd6e2e3870c6c5819a6c3db740e91ebbbc5ef4800121023f3d3b8e74b807e32217dea2c75c8d0bd46b8665b3a2d9b3cb310959de52a09bc9d20700")
3036 .as_slice()).unwrap();
3037 let spent3: Transaction = deserialize(hex!("01000000027a1120a30cef95422638e8dab9dedf720ec614b1b21e451a4957a5969afb869d000000006a47304402200ecc318a829a6cad4aa9db152adbf09b0cd2de36f47b53f5dade3bc7ef086ca702205722cda7404edd6012eedd79b2d6f24c0a0c657df1a442d0a2166614fb164a4701210372f4b97b34e9c408741cd1fc97bcc7ffdda6941213ccfde1cb4075c0f17aab06ffffffffc23b43e5a18e5a66087c0d5e64d58e8e21fcf83ce3f5e4f7ecb902b0e80a7fb6010000006b483045022100f10076a0ea4b4cf8816ed27a1065883efca230933bf2ff81d5db6258691ff75202206b001ef87624e76244377f57f0c84bc5127d0dd3f6e0ef28b276f176badb223a01210309a3a61776afd39de4ed29b622cd399d99ecd942909c36a8696cfd22fc5b5a1affffffff0200127a000000000017a914f895e1dd9b29cb228e9b06a15204e3b57feaf7cc8769311d09000000001976a9144d00da12aaa51849d2583ae64525d4a06cd70fde88ac00000000")
3038 .as_slice()).unwrap();
3039
3040 let mut spent = HashMap::new();
3041 spent.insert(spent1.compute_txid(), spent1);
3042 spent.insert(spent2.compute_txid(), spent2);
3043 spent.insert(spent3.compute_txid(), spent3);
3044 let mut spent2 = spent.clone();
3045 let mut spent3 = spent.clone();
3046
3047 spending
3048 .verify(|point: &OutPoint| {
3049 if let Some(tx) = spent.remove(&point.txid) {
3050 return tx.output.get(point.vout as usize).cloned();
3051 }
3052 None
3053 })
3054 .unwrap();
3055
3056 let mut double_spending = spending.clone();
3058 let re_use = double_spending.input[0].clone();
3059 double_spending.input.push(re_use);
3060
3061 assert!(double_spending
3062 .verify(|point: &OutPoint| {
3063 if let Some(tx) = spent2.remove(&point.txid) {
3064 return tx.output.get(point.vout as usize).cloned();
3065 }
3066 None
3067 })
3068 .is_err());
3069
3070 let mut witness: Vec<_> = spending.input[1].witness.to_vec();
3072 witness[0][10] = 42;
3073 spending.input[1].witness = Witness::from_slice(&witness);
3074
3075 let error = spending
3076 .verify(|point: &OutPoint| {
3077 if let Some(tx) = spent3.remove(&point.txid) {
3078 return tx.output.get(point.vout as usize).cloned();
3079 }
3080 None
3081 })
3082 .err()
3083 .unwrap();
3084
3085 match error {
3086 TxVerifyError::ScriptVerification(_) => {}
3087 _ => panic!("Wrong error type"),
3088 }
3089 }
3090
3091 #[test]
3092 fn sequence_number() {
3093 let seq_final = Sequence::from_consensus(0xFFFFFFFF);
3094 let seq_non_rbf = Sequence::from_consensus(0xFFFFFFFE);
3095 let block_time_lock = Sequence::from_consensus(0xFFFF);
3096 let unit_time_lock = Sequence::from_consensus(0x40FFFF);
3097 let lock_time_disabled = Sequence::from_consensus(0x80000000);
3098
3099 assert!(seq_final.is_final());
3100 assert!(!seq_final.is_rbf());
3101 assert!(!seq_final.is_relative_lock_time());
3102 assert!(!seq_non_rbf.is_rbf());
3103 assert!(block_time_lock.is_relative_lock_time());
3104 assert!(block_time_lock.is_height_locked());
3105 assert!(block_time_lock.is_rbf());
3106 assert!(unit_time_lock.is_relative_lock_time());
3107 assert!(unit_time_lock.is_time_locked());
3108 assert!(unit_time_lock.is_rbf());
3109 assert!(!lock_time_disabled.is_relative_lock_time());
3110 }
3111
3112 #[test]
3113 fn sequence_from_hex_lower() {
3114 let sequence = Sequence::from_hex("0xffffffff").unwrap();
3115 assert_eq!(sequence, Sequence::MAX);
3116 }
3117
3118 #[test]
3119 fn sequence_from_hex_upper() {
3120 let sequence = Sequence::from_hex("0XFFFFFFFF").unwrap();
3121 assert_eq!(sequence, Sequence::MAX);
3122 }
3123
3124 #[test]
3125 fn sequence_from_unprefixed_hex_lower() {
3126 let sequence = Sequence::from_unprefixed_hex("ffffffff").unwrap();
3127 assert_eq!(sequence, Sequence::MAX);
3128 }
3129
3130 #[test]
3131 fn sequence_from_unprefixed_hex_upper() {
3132 let sequence = Sequence::from_unprefixed_hex("FFFFFFFF").unwrap();
3133 assert_eq!(sequence, Sequence::MAX);
3134 }
3135
3136 #[test]
3137 fn sequence_from_str_hex_invalid_hex_should_err() {
3138 let hex = "0xzb93";
3139 let result = Sequence::from_hex(hex);
3140 assert!(result.is_err());
3141 }
3142
3143 #[test]
3144 fn effective_value_happy_path() {
3145 let value = Amount::from_str("1 cBTC").unwrap();
3146 let fee_rate = FeeRate::from_sat_per_kwu(10);
3147 let satisfaction_weight = Weight::from_wu(204);
3148 let effective_value = effective_value(fee_rate, satisfaction_weight, value).unwrap();
3149
3150 let expected_fee = SignedAmount::from_str("4 sats").unwrap();
3152 let expected_effective_value = value.to_signed().unwrap() - expected_fee;
3153 assert_eq!(effective_value, expected_effective_value);
3154 }
3155
3156 #[test]
3157 fn effective_value_fee_rate_does_not_overflow() {
3158 let eff_value = effective_value(FeeRate::MAX, Weight::ZERO, Amount::ZERO);
3159 assert!(eff_value.is_none());
3160 }
3161
3162 #[test]
3163 fn effective_value_weight_does_not_overflow() {
3164 let eff_value = effective_value(FeeRate::ZERO, Weight::MAX, Amount::ZERO);
3165 assert!(eff_value.is_none());
3166 }
3167
3168 #[test]
3169 fn effective_value_value_does_not_overflow() {
3170 let eff_value = effective_value(FeeRate::ZERO, Weight::ZERO, Amount::MAX);
3171 assert!(eff_value.is_none());
3172 }
3173
3174 #[test]
3175 fn txin_txout_weight() {
3176 let txs = [
3178 (true, "020000000001018a763b78d3e17acea0625bf9e52b0dc1beb2241b2502185348ba8ff4a253176e0100000000ffffffff0280d725000000000017a914c07ed639bd46bf7087f2ae1dfde63b815a5f8b488767fda20300000000160014869ec8520fa2801c8a01bfdd2e82b19833cd0daf02473044022016243edad96b18c78b545325aaff80131689f681079fb107a67018cb7fb7830e02205520dae761d89728f73f1a7182157f6b5aecf653525855adb7ccb998c8e6143b012103b9489bde92afbcfa85129a82ffa512897105d1a27ad9806bded27e0532fc84e700000000", Weight::from_wu(565)),
3180 (true, "01000000000101a3ccad197118a2d4975fadc47b90eacfdeaf8268adfdf10ed3b4c3b7e1ad14530300000000ffffffff0200cc5501000000001976a91428ec6f21f4727bff84bb844e9697366feeb69f4d88aca2a5100d00000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220548f11130353b3a8f943d2f14260345fc7c20bde91704c9f1cbb5456355078cd0220383ed4ed39b079b618bcb279bbc1f2ca18cb028c4641cb522c9c5868c52a0dc20147304402203c332ecccb3181ca82c0600520ee51fee80d3b4a6ab110945e59475ec71e44ac0220679a11f3ca9993b04ccebda3c834876f353b065bb08f50076b25f5bb93c72ae1016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000", Weight::from_wu(766)),
3182 (true, "010000000001036b6b6ac7e34e97c53c1cc74c99c7948af2e6aac75d8778004ae458d813456764000000006a473044022001deec7d9075109306320b3754188f81a8236d0d232b44bc69f8309115638b8f02204e17a5194a519cf994d0afeea1268740bdc10616b031a521113681cc415e815c012103488d3272a9fad78ee887f0684cb8ebcfc06d0945e1401d002e590c7338b163feffffffffc75bd7aa6424aee972789ec28ba181254ee6d8311b058d165bd045154d7660b0000000006b483045022100c8641bcbee3e4c47a00417875015d8c5d5ea918fb7e96f18c6ffe51bc555b401022074e2c46f5b1109cd79e39a9aa203eadd1d75356415e51d80928a5fb5feb0efee0121033504b4c6dfc3a5daaf7c425aead4c2dbbe4e7387ce8e6be2648805939ecf7054ffffffff494df3b205cd9430a26f8e8c0dc0bb80496fbc555a524d6ea307724bc7e60eee0100000000ffffffff026d861500000000001976a9145c54ed1360072ebaf56e87693b88482d2c6a101588ace407000000000000160014761e31e2629c6e11936f2f9888179d60a5d4c1f900000247304402201fa38a67a63e58b67b6cfffd02f59121ca1c8a1b22e1efe2573ae7e4b4f06c2b022002b9b431b58f6e36b3334fb14eaecee7d2f06967a77ef50d8d5f90dda1057f0c01210257dc6ce3b1100903306f518ee8fa113d778e403f118c080b50ce079fba40e09a00000000", Weight::from_wu(1755)),
3184 (false, "0100000003e4d7be4314204a239d8e00691128dca7927e19a7339c7948bde56f669d27d797010000006b483045022100b988a858e2982e2daaf0755b37ad46775d6132057934877a5badc91dee2f66ff022020b967c1a2f0916007662ec609987e951baafa6d4fda23faaad70715611d6a2501210254a2dccd8c8832d4677dc6f0e562eaaa5d11feb9f1de2c50a33832e7c6190796ffffffff9e22eb1b3f24c260187d716a8a6c2a7efb5af14a30a4792a6eeac3643172379c000000006a47304402207df07f0cd30dca2cf7bed7686fa78d8a37fe9c2254dfdca2befed54e06b779790220684417b8ff9f0f6b480546a9e90ecee86a625b3ea1e4ca29b080da6bd6c5f67e01210254a2dccd8c8832d4677dc6f0e562eaaa5d11feb9f1de2c50a33832e7c6190796ffffffff1123df3bfb503b59769731da103d4371bc029f57979ebce68067768b958091a1000000006a47304402207a016023c2b0c4db9a7d4f9232fcec2193c2f119a69125ad5bcedcba56dd525e02206a734b3a321286c896759ac98ebfd9d808df47f1ce1fbfbe949891cc3134294701210254a2dccd8c8832d4677dc6f0e562eaaa5d11feb9f1de2c50a33832e7c6190796ffffffff0200c2eb0b000000001976a914e5eb3e05efad136b1405f5c2f9adb14e15a35bb488ac88cfff1b000000001976a9144846db516db3130b7a3c92253599edec6bc9630b88ac00000000", Weight::from_wu(2080)),
3186 (true, "01000000000101b5cee87f1a60915c38bb0bc26aaf2b67be2b890bbc54bb4be1e40272e0d2fe0b0000000000ffffffff025529000000000000225120106daad8a5cb2e6fc74783714273bad554a148ca2d054e7a19250e9935366f3033760000000000002200205e6d83c44f57484fd2ef2a62b6d36cdcd6b3e06b661e33fd65588a28ad0dbe060141df9d1bfce71f90d68bf9e9461910b3716466bfe035c7dbabaa7791383af6c7ef405a3a1f481488a91d33cd90b098d13cb904323a3e215523aceaa04e1bb35cdb0100000000", Weight::from_wu(617)),
3188 (false, "0100000001c336895d9fa674f8b1e294fd006b1ac8266939161600e04788c515089991b50a030000006a47304402204213769e823984b31dcb7104f2c99279e74249eacd4246dabcf2575f85b365aa02200c3ee89c84344ae326b637101a92448664a8d39a009c8ad5d147c752cbe112970121028b1b44b4903c9103c07d5a23e3c7cf7aeb0ba45ddbd2cfdce469ab197381f195fdffffff040000000000000000536a4c5058325bb7b7251cf9e36cac35d691bd37431eeea426d42cbdecca4db20794f9a4030e6cb5211fabf887642bcad98c9994430facb712da8ae5e12c9ae5ff314127d33665000bb26c0067000bb0bf00322a50c300000000000017a9145ca04fdc0a6d2f4e3f67cfeb97e438bb6287725f8750c30000000000001976a91423086a767de0143523e818d4273ddfe6d9e4bbcc88acc8465003000000001976a914c95cbacc416f757c65c942f9b6b8a20038b9b12988ac00000000", Weight::from_wu(1396)),
3190 ];
3191
3192 let empty_transaction_weight = Transaction {
3193 version: Version::TWO,
3194 lock_time: absolute::LockTime::ZERO,
3195 input: vec![],
3196 output: vec![],
3197 }
3198 .weight();
3199
3200 for (is_segwit, tx, expected_weight) in &txs {
3201 let txin_weight = if *is_segwit { TxIn::segwit_weight } else { TxIn::legacy_weight };
3202 let tx: Transaction = deserialize(Vec::from_hex(tx).unwrap().as_slice()).unwrap();
3203 assert_eq!(*is_segwit, tx.uses_segwit_serialization());
3204
3205 let mut calculated_weight = empty_transaction_weight
3206 + tx.input.iter().fold(Weight::ZERO, |sum, i| sum + txin_weight(i))
3207 + tx.output.iter().fold(Weight::ZERO, |sum, o| sum + o.weight());
3208
3209 if !tx.uses_segwit_serialization() {
3211 calculated_weight -= Weight::from_wu(2);
3212 }
3213
3214 assert_eq!(calculated_weight, *expected_weight);
3215 assert_eq!(tx.weight(), *expected_weight);
3216 }
3217 }
3218
3219 #[test]
3220 fn tx_sigop_count() {
3221 let tx_hexes = [
3222 (
3224 "0200000001725aab4d23f76ad10bb569a68f8702ebfb8b076e015179ff9b9425234953\
3225 ac63000000006a47304402204cae7dc9bb68b588dd6b8afb8b881b752fd65178c25693e\
3226 a6d5d9a08388fd2a2022011c753d522d5c327741a6d922342c86e05c928309d7e566f68\
3227 8148432e887028012103f14b11cfb58b113716e0fa277ab4a32e4d3ed64c6b09b1747ef\
3228 7c828d5b06a94fdffffff01e5d4830100000000160014e98527b55cae861e5b9c3a6794\
3229 86514c012d6fce00000000",
3230 0, return_none as fn(&OutPoint) -> Option<TxOut>, 0, ),
3234 (
3236 "020000000001018c47330b1c4d30e7e2244e8ccb56d411b71e10073bb42fa1813f3f01\
3237 e144cc4d0100000000fdffffff01f7e30300000000001976a9143b49fd16f7562cfeedc\
3238 6a4ba84805f8c2f8e1a2c88ac024830450221009a4dbf077a63f6e4c3628a5fef2a09ec\
3239 6f7ca4a4d95bc8bb69195b6b671e9272022074da9ffff5a677fc7b37d66bb4ff1f316c9\
3240 dbacb92058291d84cd4b83f7c63c9012103d013e9e53c9ca8dd2ddffab1e9df27811503\
3241 feea7eb0700ff058851bbb37d99000000000",
3242 5,
3243 return_p2wpkh,
3244 4,
3245 ),
3246 (
3248 "01000000000101e70d7b4d957122909a665070b0c5bbb693982d09e4e66b9e6b7a8390\
3249 ce65ef1f0100000000ffffffff02095f2b0000000000220020800a016ea57a08f30c273\
3250 ae7624f8f91c505ccbd3043829349533f317168248c52594500000000001976a914607f\
3251 643372477c044c6d40b814288e40832a602688ac05004730440220282943649e687b5a3\
3252 bda9403c16f363c2ee2be0ec43fb8df40a08b96a4367d47022014e8f36938eef41a09ee\
3253 d77a815b0fa120a35f25e3a185310f050959420cee360147304402201e555f894036dd5\
3254 78045701e03bf10e093d7e93cd9997e44c1fc65a7b669852302206893f7261e52c9d779\
3255 5ba39d99aad30663da43ed675c389542805469fa8eb26a014730440220510fc99bc37d6\
3256 dbfa7e8724f4802cebdb17b012aaf70ce625e22e6158b139f40022022e9b811751d491f\
3257 bdec7691b697e88ba84315f6739b9e3bd4425ac40563aed2018b5321029ddecf0cc2013\
3258 514961550e981a0b8b60e7952f70561a5bb552aa7f075e71e3c2103316195a59c35a3b2\
3259 7b6dfcc3192cc10a7a6bbccd5658dfbe98ca62a13d6a02c121034629d906165742def4e\
3260 f53c6dade5dcbf88b775774cad151e35ae8285e613b0221035826a29938de2076950811\
3261 13c58bcf61fe6adacc3aacceb21c4827765781572d54ae00000000",
3262 8,
3263 return_p2wsh,
3264 4,
3265 ),
3266 (
3268 "010000000001018aec7e0729ba5a2d284303c89b3f397e92d54472a225d28eb0ae2fa6\
3269 5a7d1a2e02000000171600145ad5db65f313ab76726eb178c2fd8f21f977838dfdfffff\
3270 f03102700000000000017a914dca89e03ba124c2c70e55533f91100f2d9dab04587f2d7\
3271 1d00000000001976a91442a34f4b0a65bc81278b665d37fd15910d261ec588ac292c3b0\
3272 00000000017a91461978dcebd0db2da0235c1ba3e8087f9fd74c57f8702473044022000\
3273 9226f8def30a8ffa53e55ca5d71a72a64cd20ae7f3112562e3413bd0731d2c0220360d2\
3274 20435e67eef7f2bf0258d1dded706e3824f06d961ba9eeaed300b16c2cc012103180cff\
3275 753d3e4ee1aa72b2b0fd72ce75956d04f4c19400a3daed0b18c3ab831e00000000",
3276 5,
3277 return_p2sh,
3278 4,
3279 ),
3280 (
3282 "010000000115fe9ec3dc964e41f5267ea26cfe505f202bf3b292627496b04bece84da9\
3283 b18903000000fc004730440220442827f1085364bda58c5884cee7b289934083362db6d\
3284 fb627dc46f6cdbf5793022078cfa524252c381f2a572f0c41486e2838ca94aa268f2384\
3285 d0e515744bf0e1e9014730440220160e49536bb29a49c7626744ee83150174c22fa40d5\
3286 8fb4cd554a907a6a7b825022045f6cf148504b334064686795f0968c689e542f475b8ef\
3287 5a5fa42383948226a3014c69522103e54bc61efbcb8eeff3a5ab2a92a75272f5f6820e3\
3288 8e3d28edb54beb06b86c0862103a553e30733d7a8df6d390d59cc136e2c9d9cf4e808f3\
3289 b6ab009beae68dd60822210291c5a54bb8b00b6f72b90af0ac0ecaf78fab026d8eded28\
3290 2ad95d4d65db268c953aeffffffff024c4f0d000000000017a9146ebf0484bd5053f727\
3291 c755a750aa4c815dfa112887a06b12020000000017a91410065dd50b3a7f299fef3b1c5\
3292 3b8216399916ab08700000000",
3293 12,
3294 return_p2sh,
3295 0,
3296 ),
3297 (
3299 "0100000000010117a31277a8ba3957be351fe4cffd080e05e07f9ee1594d638f55dd7d\
3300 707a983c01000000232200203a33fc9628c29f36a492d9fd811fd20231fbd563f7863e7\
3301 9c4dc0ed34ea84b15ffffffff033bed03000000000017a914fb00d9a49663fd8ae84339\
3302 8ae81299a1941fb8d287429404000000000017a9148fe08d81882a339cf913281eca8af\
3303 39110507c798751ab1300000000002200208819e4bac0109b659de6b9168b83238a050b\
3304 ef16278e470083b39d28d2aa5a6904004830450221009faf81f72ec9b14a39f0f0e12f0\
3305 1a7175a4fe3239cd9a015ff2085985a9b0e3f022059e1aaf96c9282298bdc9968a46d8a\
3306 d28e7299799835cf982b02c35e217caeae0147304402202b1875355ee751e0c8b21990b\
3307 7ea73bd84dfd3bd17477b40fc96552acba306ad02204913bc43acf02821a3403132aa0c\
3308 33ac1c018d64a119f6cb55dfb8f408d997ef01695221023c15bf3436c0b4089e0ed0428\
3309 5101983199d0967bd6682d278821c1e2ac3583621034d924ccabac6d190ce8343829834\
3310 cac737aa65a9abe521bcccdcc3882d97481f21035d01d092bb0ebcb793ba3ffa0aeb143\
3311 2868f5277d5d3d2a7d2bc1359ec13abbd53aee1560c00",
3312 3,
3313 return_p2sh,
3314 0,
3315 ),
3316 (
3318 "0100000001628c1726fecd23331ae9ff2872341b82d2c03180aa64f9bceefe457448db\
3319 e579020000006a47304402204799581a5b34ae5adca21ef22c55dbfcee58527127c95d0\
3320 1413820fe7556ed970220391565b24dc47ce57fe56bf029792f821a392cdb5a3d45ed85\
3321 c158997e7421390121037b2fb5b602e51c493acf4bf2d2423bcf63a09b3b99dfb7bd3c8\
3322 d74733b5d66f5ffffffff011c0300000000000069512103a29472a1848105b2225f0eca\
3323 5c35ada0b0abbc3c538818a53eca177f4f4dcd9621020c8fd41b65ae6b980c072c5a9f3\
3324 aec9f82162c92eb4c51d914348f4390ac39122102222222222222222222222222222222\
3325 222222222222222222222222222222222253ae00000000",
3326 80,
3327 return_none,
3328 80,
3329 ),
3330 ];
3331
3332 fn return_p2sh(_outpoint: &OutPoint) -> Option<TxOut> {
3334 Some(
3335 deserialize(&hex!(
3336 "cc721b000000000017a91428203c10cc8f18a77412caaa83dabaf62b8fbb0f87"
3337 ))
3338 .unwrap(),
3339 )
3340 }
3341 fn return_p2wpkh(_outpoint: &OutPoint) -> Option<TxOut> {
3342 Some(
3343 deserialize(&hex!(
3344 "e695779d000000001600141c6977423aa4b82a0d7f8496cdf3fc2f8b4f580c"
3345 ))
3346 .unwrap(),
3347 )
3348 }
3349 fn return_p2wsh(_outpoint: &OutPoint) -> Option<TxOut> {
3350 Some(
3351 deserialize(&hex!(
3352 "66b51e0900000000220020dbd6c9d5141617eff823176aa226eb69153c1e31334ac37469251a2539fc5c2b"
3353 ))
3354 .unwrap(),
3355 )
3356 }
3357 fn return_none(_outpoint: &OutPoint) -> Option<TxOut> { None }
3358
3359 for (hx, expected, spent_fn, expected_none) in tx_hexes.iter() {
3360 let tx_bytes = hex!(hx);
3361 let tx: Transaction = deserialize(&tx_bytes).unwrap();
3362 assert_eq!(tx.total_sigop_cost(spent_fn), *expected);
3363 assert_eq!(tx.total_sigop_cost(return_none), *expected_none);
3364 }
3365 }
3366
3367 #[test]
3368 fn weight_predictions() {
3369 let tx_raw = hex!(
3371 "01000000000103fc9aa70afba04da865f9821734b556cca9fb5710\
3372 fc1338b97fba811033f755e308000000000000000019b37457784d\
3373 d04936f011f733b8016c247a9ef08d40007a54a5159d1fc62ee216\
3374 00000000000000004c4f2937c6ccf8256d9711a19df1ae62172297\
3375 0bf46be925ff15f490efa1633d01000000000000000002c0e1e400\
3376 0000000017a9146983f776902c1d1d0355ae0962cb7bc69e9afbde\
3377 8706a1e600000000001600144257782711458506b89f255202d645\
3378 e25c41144702483045022100dcada0499865a49d0aab8cb113c5f8\
3379 3fd5a97abc793f97f3f53aa4b9d1192ed702202094c7934666a30d\
3380 6adb1cc9e3b6bc14d2ffebd3200f3908c40053ef2df640b5012103\
3381 15434bb59b615a383ae87316e784fc11835bb97fab33fdd2578025\
3382 e9968d516e0247304402201d90b3197650569eba4bc0e0b1e2dca7\
3383 7dfac7b80d4366f335b67e92e0546e4402203b4be1d443ad7e3a5e\
3384 a92aafbcdc027bf9ccf5fe68c0bc8f3ebb6ab806c5464c012103e0\
3385 0d92b0fe60731a54fdbcc6920934159db8ffd69d55564579b69a22\
3386 ec5bb7530247304402205ab83b734df818e64d8b9e86a8a75f9d00\
3387 5c0c6e1b988d045604853ab9ccbde002205a580235841df609d6bd\
3388 67534bdcd301999b18e74e197e9e476cdef5fdcbf822012102ebb3\
3389 e8a4638ede4721fb98e44e3a3cd61fecfe744461b85e0b6a6a1017\
3390 5d5aca00000000"
3391 );
3392
3393 let tx = Transaction::consensus_decode::<&[u8]>(&mut tx_raw.as_ref()).unwrap();
3394 let input_weights = vec![
3395 InputWeightPrediction::P2WPKH_MAX,
3396 InputWeightPrediction::ground_p2wpkh(1),
3397 InputWeightPrediction::ground_p2wpkh(1),
3398 ];
3399 let predicted = predict_weight(input_weights, tx.script_pubkey_lens());
3403 let expected = tx.weight();
3404 assert_eq!(predicted, expected);
3405
3406 assert_eq!(
3408 InputWeightPrediction::ground_p2wpkh(0).weight(),
3409 InputWeightPrediction::P2WPKH_MAX.weight()
3410 );
3411 assert_eq!(
3412 InputWeightPrediction::ground_p2pkh_compressed(0).weight(),
3413 InputWeightPrediction::P2PKH_COMPRESSED_MAX.weight()
3414 );
3415 }
3416
3417 #[test]
3418 fn sequence_debug_output() {
3419 let seq = Sequence::from_seconds_floor(1000);
3420 println!("{:?}", seq)
3421 }
3422
3423 #[test]
3424 fn outpoint_format() {
3425 let outpoint = OutPoint::default();
3426
3427 let debug = "OutPoint { txid: 0000000000000000000000000000000000000000000000000000000000000000, vout: 4294967295 }";
3428 assert_eq!(debug, format!("{:?}", outpoint));
3429
3430 let display = "0000000000000000000000000000000000000000000000000000000000000000:4294967295";
3431 assert_eq!(display, format!("{}", outpoint));
3432
3433 let pretty_debug = "OutPoint {\n txid: 0000000000000000000000000000000000000000000000000000000000000000,\n vout: 4294967295,\n}";
3434 assert_eq!(pretty_debug, format!("{:#?}", outpoint));
3435
3436 let debug_txid = "0000000000000000000000000000000000000000000000000000000000000000";
3437 assert_eq!(debug_txid, format!("{:?}", outpoint.txid));
3438
3439 let display_txid = "0000000000000000000000000000000000000000000000000000000000000000";
3440 assert_eq!(display_txid, format!("{}", outpoint.txid));
3441
3442 let pretty_txid = "0x0000000000000000000000000000000000000000000000000000000000000000";
3443 assert_eq!(pretty_txid, format!("{:#}", outpoint.txid));
3444 }
3445}
3446
3447#[cfg(bench)]
3448mod benches {
3449 use hex_lit::hex;
3450 use io::sink;
3451 use test::{black_box, Bencher};
3452
3453 use super::Transaction;
3454 use crate::consensus::{deserialize, Encodable};
3455
3456 const SOME_TX: &str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
3457
3458 #[bench]
3459 pub fn bench_transaction_size(bh: &mut Bencher) {
3460 let raw_tx = hex!(SOME_TX);
3461
3462 let mut tx: Transaction = deserialize(&raw_tx).unwrap();
3463
3464 bh.iter(|| {
3465 black_box(black_box(&mut tx).total_size());
3466 });
3467 }
3468
3469 #[bench]
3470 pub fn bench_transaction_serialize(bh: &mut Bencher) {
3471 let raw_tx = hex!(SOME_TX);
3472 let tx: Transaction = deserialize(&raw_tx).unwrap();
3473
3474 let mut data = Vec::with_capacity(raw_tx.len());
3475
3476 bh.iter(|| {
3477 let result = tx.consensus_encode(&mut data);
3478 black_box(&result);
3479 data.clear();
3480 });
3481 }
3482
3483 #[bench]
3484 pub fn bench_transaction_serialize_logic(bh: &mut Bencher) {
3485 let raw_tx = hex!(SOME_TX);
3486 let tx: Transaction = deserialize(&raw_tx).unwrap();
3487
3488 bh.iter(|| {
3489 let size = tx.consensus_encode(&mut sink());
3490 black_box(&size);
3491 });
3492 }
3493
3494 #[bench]
3495 pub fn bench_transaction_deserialize(bh: &mut Bencher) {
3496 let raw_tx = hex!(SOME_TX);
3497
3498 bh.iter(|| {
3499 let tx: Transaction = deserialize(&raw_tx).unwrap();
3500 black_box(&tx);
3501 });
3502 }
3503}