What changed, and why it matters
This commit simply moves existing unit tests from one internal crate to another and rewrites them to use a newer encoding API. No production code behavior changes, and no security bug is fixed or introduced.
No security action required; this is a routine test refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch relocates deserialization/serialization tests for Block and Transaction from the bitcoin crate to the primitives crate. Tests are adapted from the old consensus::encode::{deserialize, serialize} functions to the new encoding::{decode_from_slice, encode_to_vec} API. A binary test fixture is also moved. No runtime logic is modified.
Changed components
bitcoin/src/blockdata/block.rsbitcoin/src/blockdata/transaction.rsprimitives/src/block.rsprimitives/src/transaction.rsprimitives/tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.rawInspect captured patch +98 / −89
diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs
index edf2cd2a..8f00b2de 100644
--- a/bitcoin/src/blockdata/block.rs
+++ b/bitcoin/src/blockdata/block.rs
@@ -420,22 +420,6 @@ mod tests {
use crate::transaction::{OutPoint, Transaction, TxIn, TxOut, Txid};
use crate::{block, Amount, CompactTarget, Network, Sequence, TestnetVersion, Witness, Wtxid};
- #[test]
- fn static_vector() {
- // testnet block 000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b
- let segwit_block = include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw");
- let block: Block = deserialize(&segwit_block[..]).expect("failed to deserialize block");
- assert!(block.check_merkle_root());
-
- let (header, transactions) = block.into_parts();
- let block = Block::new_unchecked(header, transactions).assume_checked(None);
-
- // Same as `block.check_merkle_root` but do it explicitly.
- let hashes_iter = block.transactions().iter().map(|obj| obj.compute_txid());
- let from_iter = TxMerkleNode::calculate_root(hashes_iter.clone());
- assert_eq!(from_iter, Some(block.header().merkle_root));
- }
-
#[test]
fn coinbase_and_bip34() {
// testnet block 100,000
@@ -584,22 +568,6 @@ mod tests {
assert_eq!(serialize(&real_decode), segwit_block);
}
- #[test]
- fn block_version() {
- let block = hex!("ffffff7f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
- let decode: Result<Block, _> = deserialize(&block);
- assert!(decode.is_ok());
-
- let real_decode = decode.unwrap().assume_checked(None);
- assert_eq!(real_decode.header().version, Version::from_consensus(2147483647));
-
- let block2 = hex!("000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
- let decode2: Result<Block, _> = deserialize(&block2);
- assert!(decode2.is_ok());
- let real_decode2 = decode2.unwrap().assume_checked(None);
- assert_eq!(real_decode2.header().version, Version::from_consensus(-2147483648));
- }
-
#[test]
fn validate_pow() {
let some_header = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b");
diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs
index 4a30fa18..1cbd446e 100644
--- a/bitcoin/src/blockdata/transaction.rs
+++ b/bitcoin/src/blockdata/transaction.rs
@@ -1305,10 +1305,9 @@ mod tests {
use hex_unstable::hex;
use super::*;
- use crate::consensus::encode::{deserialize, serialize};
+ use crate::consensus::encode::deserialize;
use crate::constants::WITNESS_SCALE_FACTOR;
use crate::hex;
- use crate::script::ScriptSigBuf;
const SOME_TX: &str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
@@ -1323,12 +1322,6 @@ mod tests {
assert_eq!(raw_tx, &buf[..size]);
}
- #[test]
- fn txin() {
- let txin: Result<TxIn, _> = deserialize(&hex!("a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff"));
- assert!(txin.is_ok());
- }
-
#[test]
fn is_coinbase() {
use crate::constants;
@@ -1375,14 +1368,6 @@ mod tests {
assert_eq!(realtx.base_size(), tx_bytes.len());
}
- #[test]
- fn segwit_invalid_transaction() {
- let tx_bytes = hex!("0000fd000001021921212121212121212121f8b372b0239cc1dff600000000004f4f4f4f4f4f4f4f000000000000000000000000000000333732343133380d000000000000000000000000000000ff000000000009000dff000000000000000800000000000000000d");
- let tx: Result<Transaction, _> = deserialize(&tx_bytes);
- assert!(tx.is_err());
- assert!(matches!(tx.unwrap_err(), crate::consensus::DeserializeError::Parse(_)));
- }
-
#[test]
fn segwit_transaction() {
let tx_bytes = hex!(
@@ -1451,47 +1436,6 @@ mod tests {
assert_eq!(bytes, json.as_bytes())
}
- #[test]
- fn transaction_version() {
- let tx_bytes = hex!("ffffffff0100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000");
- let tx: Result<Transaction, _> = deserialize(&tx_bytes);
- assert!(tx.is_ok());
- let realtx = tx.unwrap();
- assert_eq!(realtx.version, Version::maybe_non_standard(u32::MAX));
- }
-
- #[test]
- fn tx_no_input_deserialization() {
- let tx_bytes = hex!(
- "010000000001000100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"
- );
- let tx: Transaction = deserialize(&tx_bytes).expect("deserialize tx");
-
- assert_eq!(tx.inputs.len(), 0);
- assert_eq!(tx.outputs.len(), 1);
-
- let reser = serialize(&tx);
- assert_eq!(tx_bytes, *reser);
- }
-
- #[test]
- fn ntxid() {
- let tx_bytes = hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000");
- let mut tx: Transaction = deserialize(&tx_bytes).unwrap();
-
- let old_ntxid = tx.compute_ntxid();
- assert_eq!(
- format!("{:x}", old_ntxid),
- "c3573dbea28ce24425c59a189391937e00d255150fa973d59d61caf3a06b601d"
- );
- // changing sigs does not affect it
- tx.inputs[0].script_sig = ScriptSigBuf::new();
- assert_eq!(old_ntxid, tx.compute_ntxid());
- // changing pks does
- tx.outputs[0].script_pubkey = ScriptPubKeyBuf::new();
- assert!(old_ntxid != tx.compute_ntxid());
- }
-
#[test]
fn txid() {
// SegWit tx from Liquid integration tests, txid/hash from Core decoderawtransaction
diff --git a/primitives/src/block.rs b/primitives/src/block.rs
index a1db1b03..97aa5bf6 100644
--- a/primitives/src/block.rs
+++ b/primitives/src/block.rs
@@ -1012,6 +1012,8 @@ mod tests {
#[cfg(feature = "alloc")]
use encoding::Decode as _;
use encoding::{Decoder as _, Encode as _, Encoder as _};
+ #[cfg(feature = "hex")]
+ use hex_unstable::hex;
#[cfg(feature = "alloc")]
#[cfg(feature = "hex")]
#[cfg(feature = "serde")]
@@ -2022,4 +2024,40 @@ mod tests {
let roundtrip: Adt = bincode::deserialize(&bytes).expect("failed to deserialize");
assert_eq!(roundtrip, orig);
}
+
+ #[test]
+ #[cfg(feature = "alloc")]
+ #[cfg(feature = "hex")]
+ fn block_version() {
+ let block = hex!("ffffff7f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
+ let decode: Result<Block<Unchecked>, _> = encoding::decode_from_slice(&block);
+ assert!(decode.is_ok());
+
+ let real_decode = decode.unwrap().assume_checked(None);
+ assert_eq!(real_decode.header().version, Version::from_consensus(2147483647));
+
+ let block2 = hex!("000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
+ let decode2: Result<Block<Unchecked>, _> = encoding::decode_from_slice(&block2);
+ assert!(decode2.is_ok());
+ let real_decode2 = decode2.unwrap().assume_checked(None);
+ assert_eq!(real_decode2.header().version, Version::from_consensus(-2147483648));
+ }
+
+ #[test]
+ #[cfg(feature = "alloc")]
+ fn static_vector() {
+ // testnet block 000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b
+ let segwit_block = include_bytes!("../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw");
+ let block: Block<Unchecked> =
+ encoding::decode_from_slice(&segwit_block[..]).expect("failed to deserialize block");
+ assert!(block.check_merkle_root());
+
+ let (header, transactions) = block.into_parts();
+ let block = Block::new_unchecked(header, transactions).assume_checked(None);
+
+ // Same as `block.check_merkle_root` but do it explicitly.
+ let hashes_iter = block.transactions().iter().map(|obj| obj.compute_txid());
+ let from_iter = TxMerkleNode::calculate_root(hashes_iter.clone());
+ assert_eq!(from_iter, Some(block.header().merkle_root));
+ }
}
diff --git a/primitives/src/transaction.rs b/primitives/src/transaction.rs
index 4394271e..0ce196e4 100644
--- a/primitives/src/transaction.rs
+++ b/primitives/src/transaction.rs
@@ -3246,4 +3246,63 @@ mod tests {
let tx_bytes = encoding::encode_to_vec(tx);
decode_error_from_bytes(&tx_bytes)
}
+
+ #[test]
+ #[cfg(feature = "hex")]
+ fn txin() {
+ let txin: Result<TxIn, _> = encoding::decode_from_slice(&hex!("a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff"));
+ assert!(txin.is_ok());
+ }
+
+ #[test]
+ #[cfg(feature = "hex")]
+ fn segwit_invalid_transaction() {
+ let tx_bytes = hex!("0000fd000001021921212121212121212121f8b372b0239cc1dff600000000004f4f4f4f4f4f4f4f000000000000000000000000000000333732343133380d000000000000000000000000000000ff000000000009000dff000000000000000800000000000000000d");
+ let tx: Result<Transaction, _> = encoding::decode_from_slice(&tx_bytes);
+ assert!(tx.is_err());
+ }
+
+ #[test]
+ #[cfg(feature = "hex")]
+ fn transaction_version() {
+ let tx_bytes = hex!("ffffffff0100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000");
+ let tx: Result<Transaction, _> = encoding::decode_from_slice(&tx_bytes);
+ assert!(tx.is_ok());
+ let realtx = tx.unwrap();
+ assert_eq!(realtx.version, Version::maybe_non_standard(u32::MAX));
+ }
+
+ #[test]
+ #[cfg(feature = "hex")]
+ fn tx_no_input_deserialization() {
+ let tx_bytes = hex!(
+ "010000000001000100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"
+ );
+ let tx: Transaction = encoding::decode_from_slice(&tx_bytes).expect("deserialize tx");
+
+ assert_eq!(tx.inputs.len(), 0);
+ assert_eq!(tx.outputs.len(), 1);
+
+ let reser = encoding::encode_to_vec(&tx);
+ assert_eq!(&tx_bytes[..], reser.as_slice());
+ }
+
+ #[test]
+ #[cfg(feature = "hex")]
+ fn ntxid() {
+ let tx_bytes = hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000");
+ let mut tx: Transaction = encoding::decode_from_slice(&tx_bytes).unwrap();
+
+ let old_ntxid = tx.compute_ntxid();
+ assert_eq!(
+ format!("{:x}", old_ntxid),
+ "c3573dbea28ce24425c59a189391937e00d255150fa973d59d61caf3a06b601d"
+ );
+ // changing sigs does not affect it
+ tx.inputs[0].script_sig = ScriptSigBuf::new();
+ assert_eq!(old_ntxid, tx.compute_ntxid());
+ // changing pks does
+ tx.outputs[0].script_pubkey = ScriptPubKeyBuf::new();
+ assert!(old_ntxid != tx.compute_ntxid());
+ }
}
diff --git a/primitives/tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw b/primitives/tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw
new file mode 100644
index 00000000..45376bad
Binary files /dev/null and b/primitives/tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw differ
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.