Skip to content

Commit 7699366

Browse files
committed
Merge rust-bitcoin#4911: bitcoin: add "extreme object size" deserialization unit test
1c18ed9 bitcoin: add "extreme object size" deserialization unit test (Andrew Poelstra) Pull request description: As promised in rust-bitcoin#4762 I am not convinced that our decoding of large transactions and blocks is properly tested to make sure that we don't accidentally start rejecting very large objects. Add a unit test specifically for this. ACKs for top commit: tcharding: ACK 1c18ed9 Tree-SHA512: 8271761d1bc1b5c7210c0f4871a8cce4b61305a09996d265c1c44dedcbd829fd5848f48ce976e6be348fae2a22b200f9b398c473e6d7594ff62ddacff1657ab3
2 parents fbd68fb + 1c18ed9 commit 7699366

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

bitcoin/src/consensus/encode.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,4 +1058,45 @@ mod tests {
10581058
FromHexError::Decode(DecodeError::Unconsumed)
10591059
));
10601060
}
1061+
1062+
#[test]
1063+
fn deserialize_extreme_tx() {
1064+
use crate::{ScriptSigBuf, Witness};
1065+
1066+
// Start with transaction from `deserialize_tx_hex`
1067+
let hex = include_str!("../../tests/data/previous_tx_0_hex"); // An arbitrary transaction.
1068+
let tx = deserialize_hex::<Transaction>(hex).unwrap();
1069+
1070+
assert_eq!(tx.inputs.len(), 1);
1071+
assert_eq!(tx.outputs.len(), 2);
1072+
assert_eq!(tx.inputs[0].witness.len(), 2);
1073+
1074+
// 1. Test with 4 million witnesses.
1075+
let mut tx_copy = tx.clone();
1076+
tx_copy.inputs[0].witness = Witness::from_slice(&vec![vec![]; 4_000_000]);
1077+
let roundtrip = deserialize(&serialize(&tx_copy)).unwrap();
1078+
assert_eq!(tx_copy, roundtrip);
1079+
1080+
// 2. Test with a single large witness. (Size of 4 megs, including length prefix)
1081+
let mut tx_copy = tx.clone();
1082+
tx_copy.inputs[0].witness = Witness::from_slice(&vec![vec![0; 4_000_000 - 9]; 1]);
1083+
let roundtrip = deserialize(&serialize(&tx_copy)).unwrap();
1084+
assert_eq!(tx_copy, roundtrip);
1085+
1086+
// 3. Combine these; with the witness stack we can exceed a total size of 4M but
1087+
// only by a tiny bit. (It is not part of our API guarantee that such things
1088+
// will round-trip, but we unit test them anyway to help notice changes.)
1089+
let mut tx_copy = tx.clone();
1090+
tx_copy.inputs[0].witness = Witness::from_slice(&vec![vec![0; 997]; 4_000]);
1091+
let roundtrip = deserialize(&serialize(&tx_copy)).unwrap();
1092+
assert_eq!(tx_copy, roundtrip);
1093+
1094+
// 4. Test with a large script sig. With scriptsigs there is no limit on how large
1095+
// an object we can parse, which is inconsistent with witnesses. Also not an
1096+
// API guarantee.
1097+
let mut tx_copy = tx.clone();
1098+
tx_copy.inputs[0].script_sig = ScriptSigBuf::from(vec![0; 8_000_001]);
1099+
let roundtrip = deserialize(&serialize(&tx_copy)).unwrap();
1100+
assert_eq!(tx_copy, roundtrip);
1101+
}
10611102
}

0 commit comments

Comments
 (0)