Merge pull request #392 from instagibbs/wit_scale

Add, use WITNESS_SCALE_FACTOR constant
This commit is contained in:
Elichai Turkel 2020-01-20 18:02:59 +02:00 committed by GitHub
commit 5452260884
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 24 deletions

View File

@ -44,6 +44,8 @@ pub const DIFFCHANGE_TIMESPAN: u32 = 14 * 24 * 3600;
pub const MAX_BLOCK_WEIGHT: u32 = 4_000_000; pub const MAX_BLOCK_WEIGHT: u32 = 4_000_000;
/// The minimum transaction weight for a valid serialized transaction /// The minimum transaction weight for a valid serialized transaction
pub const MIN_TRANSACTION_WEIGHT: u32 = 4 * 60; pub const MIN_TRANSACTION_WEIGHT: u32 = 4 * 60;
/// The factor that non-witness serialization data is multiplied by during weight calculation
pub const WITNESS_SCALE_FACTOR: usize = 4;
/// In Bitcoind this is insanely described as ~((u256)0 >> 32) /// In Bitcoind this is insanely described as ~((u256)0 >> 32)

View File

@ -30,6 +30,7 @@ use hashes::{self, Hash, sha256d};
use hashes::hex::FromHex; use hashes::hex::FromHex;
use util::endian; use util::endian;
use blockdata::constants::WITNESS_SCALE_FACTOR;
#[cfg(feature="bitcoinconsensus")] use blockdata::script; #[cfg(feature="bitcoinconsensus")] use blockdata::script;
use blockdata::script::Script; use blockdata::script::Script;
use consensus::{encode, serialize, Decodable, Encodable}; use consensus::{encode, serialize, Decodable, Encodable};
@ -391,7 +392,7 @@ impl Transaction {
let mut input_weight = 0; let mut input_weight = 0;
let mut inputs_with_witnesses = 0; let mut inputs_with_witnesses = 0;
for input in &self.input { for input in &self.input {
input_weight += 4*(32 + 4 + 4 + // outpoint (32+4) + nSequence input_weight += WITNESS_SCALE_FACTOR*(32 + 4 + 4 + // outpoint (32+4) + nSequence
VarInt(input.script_sig.len() as u64).len() + VarInt(input.script_sig.len() as u64).len() +
input.script_sig.len()); input.script_sig.len());
if !input.witness.is_empty() { if !input.witness.is_empty() {
@ -418,9 +419,9 @@ impl Transaction {
// lock_time // lock_time
4; 4;
if inputs_with_witnesses == 0 { if inputs_with_witnesses == 0 {
non_input_size * 4 + input_weight non_input_size * WITNESS_SCALE_FACTOR + input_weight
} else { } else {
non_input_size * 4 + input_weight + self.input.len() - inputs_with_witnesses + 2 non_input_size * WITNESS_SCALE_FACTOR + input_weight + self.input.len() - inputs_with_witnesses + 2
} }
} }
@ -623,6 +624,7 @@ mod tests {
use super::{OutPoint, ParseOutPointError, Transaction, TxIn}; use super::{OutPoint, ParseOutPointError, Transaction, TxIn};
use std::str::FromStr; use std::str::FromStr;
use blockdata::constants::WITNESS_SCALE_FACTOR;
use blockdata::script::Script; use blockdata::script::Script;
use consensus::encode::serialize; use consensus::encode::serialize;
use consensus::encode::deserialize; use consensus::encode::deserialize;
@ -688,15 +690,15 @@ mod tests {
let genesis = constants::genesis_block(Network::Bitcoin); let genesis = constants::genesis_block(Network::Bitcoin);
assert! (genesis.txdata[0].is_coin_base()); assert! (genesis.txdata[0].is_coin_base());
let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let tx_bytes = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
let tx: Transaction = deserialize(&hex_tx).unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap();
assert!(!tx.is_coin_base()); assert!(!tx.is_coin_base());
} }
#[test] #[test]
fn test_nonsegwit_transaction() { fn test_nonsegwit_transaction() {
let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let tx_bytes = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
let tx: Result<Transaction, _> = deserialize(&hex_tx); let tx: Result<Transaction, _> = deserialize(&tx_bytes);
assert!(tx.is_ok()); assert!(tx.is_ok());
let realtx = tx.unwrap(); let realtx = tx.unwrap();
// All these tests aren't really needed because if they fail, the hash check at the end // All these tests aren't really needed because if they fail, the hash check at the end
@ -715,19 +717,19 @@ mod tests {
"a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string()); "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string());
assert_eq!(format!("{:x}", realtx.wtxid()), assert_eq!(format!("{:x}", realtx.wtxid()),
"a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string()); "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string());
assert_eq!(realtx.get_weight(), 193*4); assert_eq!(realtx.get_weight(), tx_bytes.len()*WITNESS_SCALE_FACTOR);
} }
#[test] #[test]
fn test_segwit_transaction() { fn test_segwit_transaction() {
let hex_tx = Vec::<u8>::from_hex( let tx_bytes = Vec::<u8>::from_hex(
"02000000000101595895ea20179de87052b4046dfe6fd515860505d6511a9004cf12a1f93cac7c01000000\ "02000000000101595895ea20179de87052b4046dfe6fd515860505d6511a9004cf12a1f93cac7c01000000\
00ffffffff01deb807000000000017a9140f3444e271620c736808aa7b33e370bd87cb5a078702483045022\ 00ffffffff01deb807000000000017a9140f3444e271620c736808aa7b33e370bd87cb5a078702483045022\
100fb60dad8df4af2841adc0346638c16d0b8035f5e3f3753b88db122e70c79f9370220756e6633b17fd271\ 100fb60dad8df4af2841adc0346638c16d0b8035f5e3f3753b88db122e70c79f9370220756e6633b17fd271\
0e626347d28d60b0a2d6cbb41de51740644b9fb3ba7751040121028fa937ca8cba2197a37c007176ed89410\ 0e626347d28d60b0a2d6cbb41de51740644b9fb3ba7751040121028fa937ca8cba2197a37c007176ed89410\
55d3bcb8627d085e94553e62f057dcc00000000" 55d3bcb8627d085e94553e62f057dcc00000000"
).unwrap(); ).unwrap();
let tx: Result<Transaction, _> = deserialize(&hex_tx); let tx: Result<Transaction, _> = deserialize(&tx_bytes);
assert!(tx.is_ok()); assert!(tx.is_ok());
let realtx = tx.unwrap(); let realtx = tx.unwrap();
// All these tests aren't really needed because if they fail, the hash check at the end // All these tests aren't really needed because if they fail, the hash check at the end
@ -751,22 +753,22 @@ mod tests {
#[test] #[test]
fn tx_no_input_deserialization() { fn tx_no_input_deserialization() {
let hex_tx = Vec::<u8>::from_hex( let tx_bytes = Vec::<u8>::from_hex(
"010000000001000100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000" "010000000001000100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"
).unwrap(); ).unwrap();
let tx: Transaction = deserialize(&hex_tx).expect("deserialize tx"); let tx: Transaction = deserialize(&tx_bytes).expect("deserialize tx");
assert_eq!(tx.input.len(), 0); assert_eq!(tx.input.len(), 0);
assert_eq!(tx.output.len(), 1); assert_eq!(tx.output.len(), 1);
let reser = serialize(&tx); let reser = serialize(&tx);
assert_eq!(hex_tx, reser); assert_eq!(tx_bytes, reser);
} }
#[test] #[test]
fn test_ntxid() { fn test_ntxid() {
let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let tx_bytes = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
let mut tx: Transaction = deserialize(&hex_tx).unwrap(); let mut tx: Transaction = deserialize(&tx_bytes).unwrap();
let old_ntxid = tx.ntxid(); let old_ntxid = tx.ntxid();
assert_eq!(format!("{:x}", old_ntxid), "c3573dbea28ce24425c59a189391937e00d255150fa973d59d61caf3a06b601d"); assert_eq!(format!("{:x}", old_ntxid), "c3573dbea28ce24425c59a189391937e00d255150fa973d59d61caf3a06b601d");
@ -781,7 +783,7 @@ mod tests {
#[test] #[test]
fn test_txid() { fn test_txid() {
// segwit tx from Liquid integration tests, txid/hash from Core decoderawtransaction // segwit tx from Liquid integration tests, txid/hash from Core decoderawtransaction
let hex_tx = Vec::<u8>::from_hex( let tx_bytes = Vec::<u8>::from_hex(
"01000000000102ff34f95a672bb6a4f6ff4a7e90fa8c7b3be7e70ffc39bc99be3bda67942e836c00000000\ "01000000000102ff34f95a672bb6a4f6ff4a7e90fa8c7b3be7e70ffc39bc99be3bda67942e836c00000000\
23220020cde476664d3fa347b8d54ef3aee33dcb686a65ced2b5207cbf4ec5eda6b9b46e4f414d4c934ad8\ 23220020cde476664d3fa347b8d54ef3aee33dcb686a65ced2b5207cbf4ec5eda6b9b46e4f414d4c934ad8\
1d330314e888888e3bd22c7dde8aac2ca9227b30d7c40093248af7812201000000232200200af6f6a071a6\ 1d330314e888888e3bd22c7dde8aac2ca9227b30d7c40093248af7812201000000232200200af6f6a071a6\
@ -811,14 +813,14 @@ mod tests {
5a2b5e0e09a535e61690647021023222ceec58b94bd25925dd9743dae6b928737491bd940fc5dd7c6f5d5f\ 5a2b5e0e09a535e61690647021023222ceec58b94bd25925dd9743dae6b928737491bd940fc5dd7c6f5d5f\
2adc1e53ae00000000" 2adc1e53ae00000000"
).unwrap(); ).unwrap();
let tx: Transaction = deserialize(&hex_tx).unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap();
assert_eq!(format!("{:x}", tx.wtxid()), "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4"); assert_eq!(format!("{:x}", tx.wtxid()), "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4");
assert_eq!(format!("{:x}", tx.txid()), "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec"); assert_eq!(format!("{:x}", tx.txid()), "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec");
assert_eq!(tx.get_weight(), 2718); assert_eq!(tx.get_weight(), 2718);
// non-segwit tx from my mempool // non-segwit tx from my mempool
let hex_tx = Vec::<u8>::from_hex( let tx_bytes = Vec::<u8>::from_hex(
"01000000010c7196428403d8b0c88fcb3ee8d64f56f55c8973c9ab7dd106bb4f3527f5888d000000006a47\ "01000000010c7196428403d8b0c88fcb3ee8d64f56f55c8973c9ab7dd106bb4f3527f5888d000000006a47\
30440220503a696f55f2c00eee2ac5e65b17767cd88ed04866b5637d3c1d5d996a70656d02202c9aff698f\ 30440220503a696f55f2c00eee2ac5e65b17767cd88ed04866b5637d3c1d5d996a70656d02202c9aff698f\
343abb6d176704beda63fcdec503133ea4f6a5216b7f925fa9910c0121024d89b5a13d6521388969209df2\ 343abb6d176704beda63fcdec503133ea4f6a5216b7f925fa9910c0121024d89b5a13d6521388969209df2\
@ -826,7 +828,7 @@ mod tests {
bcfd08473d2b76b02a48f8c69088ac0000000000000000296a273236303039343836393731373233313237\ bcfd08473d2b76b02a48f8c69088ac0000000000000000296a273236303039343836393731373233313237\
3633313032313332353630353838373931323132373000000000" 3633313032313332353630353838373931323132373000000000"
).unwrap(); ).unwrap();
let tx: Transaction = deserialize(&hex_tx).unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap();
assert_eq!(format!("{:x}", tx.wtxid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"); assert_eq!(format!("{:x}", tx.wtxid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd");
assert_eq!(format!("{:x}", tx.txid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd"); assert_eq!(format!("{:x}", tx.txid()), "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd");
@ -835,8 +837,8 @@ mod tests {
#[test] #[test]
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
fn test_txn_encode_decode() { fn test_txn_encode_decode() {
let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let tx_bytes = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
let tx: Transaction = deserialize(&hex_tx).unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap();
serde_round_trip!(tx); serde_round_trip!(tx);
} }
@ -856,13 +858,13 @@ mod tests {
#[test] #[test]
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
fn test_segwit_tx_decode() { fn test_segwit_tx_decode() {
let hex_tx = Vec::<u8>::from_hex("010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); let tx_bytes = Vec::<u8>::from_hex("010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
let tx: Transaction = deserialize(&hex_tx).unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap();
assert_eq!(tx.get_weight(), 780); assert_eq!(tx.get_weight(), 780);
serde_round_trip!(tx); serde_round_trip!(tx);
let consensus_encoded = serialize(&tx); let consensus_encoded = serialize(&tx);
assert_eq!(consensus_encoded, hex_tx); assert_eq!(consensus_encoded, tx_bytes);
} }