From 9536a9947c2b46c7fe74a115702a97d834456281 Mon Sep 17 00:00:00 2001 From: yancy Date: Tue, 29 Aug 2023 15:07:23 +0200 Subject: [PATCH 1/5] Add base_size test --- bitcoin/src/blockdata/block.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index 6bf578fc..2912d43f 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -487,6 +487,7 @@ mod tests { assert_eq!(real_decode.header.difficulty_float(), 1.0); // [test] TODO: check the transaction data + assert_eq!(real_decode.base_size(), 81); assert_eq!(real_decode.size(), some_block.len()); assert_eq!(real_decode.stripped_size(), Weight::from_wu_usize(some_block.len())); assert_eq!( From 97b7a2dee9ad6bb2aade4d036ee7505813cb385b Mon Sep 17 00:00:00 2001 From: yancy Date: Tue, 29 Aug 2023 15:11:47 +0200 Subject: [PATCH 2/5] Use Weight type for block base_size --- bitcoin/src/blockdata/block.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index 2912d43f..3979fb1f 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -276,14 +276,16 @@ impl Block { } /// base_size == size of header + size of encoded transaction count. - fn base_size(&self) -> usize { 80 + VarInt::from(self.txdata.len()).len() } + fn base_size(&self) -> Weight { + Weight::from_wu_usize(80 + VarInt::from(self.txdata.len()).len()) + } /// Returns the size of the block. /// /// size == size of header + size of encoded transaction count + total size of transactions. pub fn size(&self) -> usize { let txs_size: usize = self.txdata.iter().map(Transaction::size).sum(); - self.base_size() + txs_size + self.base_size().to_wu() as usize + txs_size } /// Returns the stripped size of the block. @@ -296,12 +298,12 @@ impl Block { /// Returns the stripped size of the block. pub fn stripped_size(&self) -> Weight { let txs_size: Weight = self.txdata.iter().map(Transaction::stripped_size).sum(); - Weight::from_wu_usize(self.base_size()) + txs_size + self.base_size() + txs_size } /// Returns the weight of the block. pub fn weight(&self) -> Weight { - let base_weight = Weight::from_non_witness_data_size(self.base_size() as u64); + let base_weight = self.base_size() * Weight::WITNESS_SCALE_FACTOR; let txs_weight: Weight = self.txdata.iter().map(Transaction::weight).sum(); base_weight + txs_weight } @@ -487,7 +489,7 @@ mod tests { assert_eq!(real_decode.header.difficulty_float(), 1.0); // [test] TODO: check the transaction data - assert_eq!(real_decode.base_size(), 81); + assert_eq!(real_decode.base_size(), Weight::from_wu(81)); assert_eq!(real_decode.size(), some_block.len()); assert_eq!(real_decode.stripped_size(), Weight::from_wu_usize(some_block.len())); assert_eq!( From e746341f331e4518811344a7beca142c8463e3fc Mon Sep 17 00:00:00 2001 From: yancy Date: Tue, 29 Aug 2023 15:13:25 +0200 Subject: [PATCH 3/5] Add tests for scaled_size --- bitcoin/src/blockdata/transaction.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index 04beace8..ec74bfc6 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -1397,6 +1397,7 @@ mod tests { assert_eq!(realtx.size(), tx_bytes.len()); assert_eq!(realtx.vsize(), tx_bytes.len()); assert_eq!(realtx.stripped_size(), Weight::from_wu_usize(tx_bytes.len())); + assert_eq!(realtx.scaled_size(4), 772); } #[test] @@ -1457,6 +1458,7 @@ mod tests { assert_eq!(Weight::from_wu_usize(tx_without_witness.size()), expected_strippedsize); assert_eq!(Weight::from_wu_usize(tx_without_witness.vsize()), expected_strippedsize); assert_eq!(tx_without_witness.stripped_size(), expected_strippedsize); + assert_eq!(tx_without_witness.scaled_size(1), 83); } // We temporarily abuse `Transaction` for testing consensus serde adapter. From f796d6fef9bac322140e0eedb42b4ed5c58df498 Mon Sep 17 00:00:00 2001 From: yancy Date: Tue, 29 Aug 2023 15:17:16 +0200 Subject: [PATCH 4/5] Use Weight type for scaled_size --- bitcoin/src/blockdata/transaction.rs | 43 ++++++++++++++-------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index ec74bfc6..a1a0ddc3 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -693,7 +693,7 @@ impl Transaction { /// Returns the regular byte-wise consensus-serialized size of this transaction. #[inline] - pub fn size(&self) -> usize { self.scaled_size(1) } + pub fn size(&self) -> usize { self.scaled_size(1).to_wu() as usize } /// Returns the "virtual size" (vsize) of this transaction. /// @@ -741,39 +741,40 @@ impl Transaction { } /// Internal utility function for size/weight functions. - fn scaled_size(&self, scale_factor: usize) -> usize { - let mut input_weight = 0; + fn scaled_size(&self, scale_factor: u64) -> Weight { + let mut input_weight: Weight = Weight::ZERO; let mut inputs_with_witnesses = 0; for input in &self.input { - input_weight += scale_factor - * (TxIn::BASE_WEIGHT.to_wu() as usize - + VarInt(input.script_sig.len() as u64).len() - + input.script_sig.len()); + let non_scaled_input_weight: Weight = TxIn::BASE_WEIGHT + + Weight::from_wu_usize(VarInt(input.script_sig.len() as u64).len()) + + Weight::from_wu_usize(input.script_sig.len()); + input_weight += non_scaled_input_weight * scale_factor; if !input.witness.is_empty() { inputs_with_witnesses += 1; - input_weight += input.witness.serialized_len(); + input_weight += Weight::from_wu_usize(input.witness.serialized_len()); } } - let mut output_size = 0; + let mut output_size = Weight::ZERO; for output in &self.output { - output_size += 8 + // value - VarInt(output.script_pubkey.len() as u64).len() + - output.script_pubkey.len(); + output_size += Weight::from_wu(8)+ // value + Weight::from_wu_usize(VarInt(output.script_pubkey.len() as u64).len()) + + Weight::from_wu_usize(output.script_pubkey.len()); } let non_input_size = // version: - 4 + + Weight::from_wu(4) + // count varints: - VarInt(self.input.len() as u64).len() + - VarInt(self.output.len() as u64).len() + + Weight::from_wu_usize(VarInt(self.input.len() as u64).len()) + + Weight::from_wu_usize(VarInt(self.output.len() as u64).len()) + output_size + // lock_time - 4; + Weight::from_wu(4); if inputs_with_witnesses == 0 { - non_input_size * scale_factor + input_weight + non_input_size.checked_mul(scale_factor).unwrap() + input_weight } else { - non_input_size * scale_factor + input_weight + self.input.len() - inputs_with_witnesses - + 2 + non_input_size.checked_mul(scale_factor).unwrap() + + input_weight + + Weight::from_wu_usize(self.input.len() - inputs_with_witnesses + 2) } } @@ -1397,7 +1398,7 @@ mod tests { assert_eq!(realtx.size(), tx_bytes.len()); assert_eq!(realtx.vsize(), tx_bytes.len()); assert_eq!(realtx.stripped_size(), Weight::from_wu_usize(tx_bytes.len())); - assert_eq!(realtx.scaled_size(4), 772); + assert_eq!(realtx.scaled_size(4), Weight::from_wu(772)); } #[test] @@ -1458,7 +1459,7 @@ mod tests { assert_eq!(Weight::from_wu_usize(tx_without_witness.size()), expected_strippedsize); assert_eq!(Weight::from_wu_usize(tx_without_witness.vsize()), expected_strippedsize); assert_eq!(tx_without_witness.stripped_size(), expected_strippedsize); - assert_eq!(tx_without_witness.scaled_size(1), 83); + assert_eq!(tx_without_witness.scaled_size(1), Weight::from_wu(83)); } // We temporarily abuse `Transaction` for testing consensus serde adapter. From a68c42e11365e7381695b03f920af063e9c6339b Mon Sep 17 00:00:00 2001 From: yancy Date: Tue, 29 Aug 2023 15:20:05 +0200 Subject: [PATCH 5/5] Remove test from Transaction test names --- bitcoin/src/blockdata/transaction.rs | 34 ++++++++++++++-------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index a1a0ddc3..8114929f 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -1263,7 +1263,7 @@ mod tests { } #[test] - fn test_outpoint() { + fn outpoint() { assert_eq!(OutPoint::from_str("i don't care"), Err(ParseOutPointError::Format)); assert_eq!( OutPoint::from_str( @@ -1339,13 +1339,13 @@ mod tests { } #[test] - fn test_txin() { + fn txin() { let txin: Result = deserialize(&hex!("a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff")); assert!(txin.is_ok()); } #[test] - fn test_txin_default() { + fn txin_default() { let txin = TxIn::default(); assert_eq!(txin.previous_output, OutPoint::default()); assert_eq!(txin.script_sig, ScriptBuf::new()); @@ -1355,7 +1355,7 @@ mod tests { } #[test] - fn test_is_coinbase() { + fn is_coinbase() { use crate::blockdata::constants; use crate::network::Network; @@ -1367,7 +1367,7 @@ mod tests { } #[test] - fn test_nonsegwit_transaction() { + fn nonsegwit_transaction() { let tx_bytes = hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"); let tx: Result = deserialize(&tx_bytes); assert!(tx.is_ok()); @@ -1402,7 +1402,7 @@ mod tests { } #[test] - fn test_segwit_transaction() { + fn segwit_transaction() { let tx_bytes = hex!( "02000000000101595895ea20179de87052b4046dfe6fd515860505d6511a9004cf12a1f93cac7c01000000\ 00ffffffff01deb807000000000017a9140f3444e271620c736808aa7b33e370bd87cb5a078702483045022\ @@ -1465,7 +1465,7 @@ mod tests { // We temporarily abuse `Transaction` for testing consensus serde adapter. #[cfg(feature = "serde")] #[test] - fn test_consensus_serde() { + fn consensus_serde() { use crate::consensus::serde as con_serde; let json = "\"010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000\""; let mut deserializer = serde_json::Deserializer::from_str(json); @@ -1482,7 +1482,7 @@ mod tests { } #[test] - fn test_transaction_version() { + fn transaction_version() { let tx_bytes = hex!("ffffff7f0100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"); let tx: Result = deserialize(&tx_bytes); assert!(tx.is_ok()); @@ -1511,7 +1511,7 @@ mod tests { } #[test] - fn test_ntxid() { + fn ntxid() { let tx_bytes = hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"); let mut tx: Transaction = deserialize(&tx_bytes).unwrap(); @@ -1529,7 +1529,7 @@ mod tests { } #[test] - fn test_txid() { + fn txid() { // segwit tx from Liquid integration tests, txid/hash from Core decoderawtransaction let tx_bytes = hex!( "01000000000102ff34f95a672bb6a4f6ff4a7e90fa8c7b3be7e70ffc39bc99be3bda67942e836c00000000\ @@ -1596,7 +1596,7 @@ mod tests { #[test] #[cfg(feature = "serde")] - fn test_txn_encode_decode() { + fn txn_encode_decode() { let tx_bytes = hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"); let tx: Transaction = deserialize(&tx_bytes).unwrap(); serde_round_trip!(tx); @@ -1606,7 +1606,7 @@ mod tests { // from testnet, which is the first BIP144-encoded transaction I encountered. #[test] #[cfg(feature = "serde")] - fn test_segwit_tx_decode() { + fn segwit_tx_decode() { let tx_bytes = hex!("010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000"); let tx: Transaction = deserialize(&tx_bytes).unwrap(); assert_eq!(tx.weight(), Weight::from_wu(780)); @@ -1617,7 +1617,7 @@ mod tests { } #[test] - fn test_sighashtype_fromstr_display() { + fn sighashtype_fromstr_display() { let sighashtypes = vec![ ("SIGHASH_ALL", EcdsaSighashType::All), ("SIGHASH_NONE", EcdsaSighashType::None), @@ -1651,14 +1651,14 @@ mod tests { } #[test] - fn test_huge_witness() { + fn huge_witness() { deserialize::(&hex!(include_str!("../../tests/data/huge_witness.hex").trim())) .unwrap(); } #[test] #[cfg(feature = "bitcoinconsensus")] - fn test_transaction_verify() { + fn transaction_verify() { use std::collections::HashMap; use crate::blockdata::witness::Witness; @@ -1723,7 +1723,7 @@ mod tests { } #[test] - fn sequence_number_tests() { + fn sequence_number() { let seq_final = Sequence::from_consensus(0xFFFFFFFF); let seq_non_rbf = Sequence::from_consensus(0xFFFFFFFE); let block_time_lock = Sequence::from_consensus(0xFFFF); @@ -1763,7 +1763,7 @@ mod tests { } #[test] - fn txin_txout_weight_tests() { + fn txin_txout_weight() { // [(is_segwit, tx_hex, expected_weight)] let txs = [ // one segwit input (P2WPKH)