Merge pull request #626 from visvirial/impl-vsize
Implement `Block.get_strippedsize()` and `Transaction.get_vsize()`
This commit is contained in:
commit
697e8f5194
|
@ -233,17 +233,27 @@ impl Block {
|
||||||
bitcoin_merkle_root(hashes).into()
|
bitcoin_merkle_root(hashes).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The size of the header + the size of the varint with the tx count + the txs themselves
|
||||||
|
#[inline]
|
||||||
|
fn get_base_size(&self) -> usize {
|
||||||
|
80 + VarInt(self.txdata.len() as u64).len()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the size of the block
|
/// Get the size of the block
|
||||||
pub fn get_size(&self) -> usize {
|
pub fn get_size(&self) -> usize {
|
||||||
// The size of the header + the size of the varint with the tx count + the txs themselves
|
|
||||||
let base_size = 80 + VarInt(self.txdata.len() as u64).len();
|
|
||||||
let txs_size: usize = self.txdata.iter().map(Transaction::get_size).sum();
|
let txs_size: usize = self.txdata.iter().map(Transaction::get_size).sum();
|
||||||
base_size + txs_size
|
self.get_base_size() + txs_size
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the strippedsize of the block
|
||||||
|
pub fn get_strippedsize(&self) -> usize {
|
||||||
|
let txs_size: usize = self.txdata.iter().map(Transaction::get_strippedsize).sum();
|
||||||
|
self.get_base_size() + txs_size
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the weight of the block
|
/// Get the weight of the block
|
||||||
pub fn get_weight(&self) -> usize {
|
pub fn get_weight(&self) -> usize {
|
||||||
let base_weight = WITNESS_SCALE_FACTOR * (80 + VarInt(self.txdata.len() as u64).len());
|
let base_weight = WITNESS_SCALE_FACTOR * self.get_base_size();
|
||||||
let txs_weight: usize = self.txdata.iter().map(Transaction::get_weight).sum();
|
let txs_weight: usize = self.txdata.iter().map(Transaction::get_weight).sum();
|
||||||
base_weight + txs_weight
|
base_weight + txs_weight
|
||||||
}
|
}
|
||||||
|
@ -372,6 +382,7 @@ mod tests {
|
||||||
// [test] TODO: check the transaction data
|
// [test] TODO: check the transaction data
|
||||||
|
|
||||||
assert_eq!(real_decode.get_size(), some_block.len());
|
assert_eq!(real_decode.get_size(), some_block.len());
|
||||||
|
assert_eq!(real_decode.get_strippedsize(), some_block.len());
|
||||||
assert_eq!(real_decode.get_weight(), some_block.len() * 4);
|
assert_eq!(real_decode.get_weight(), some_block.len() * 4);
|
||||||
|
|
||||||
// should be also ok for a non-witness block as commitment is optional in that case
|
// should be also ok for a non-witness block as commitment is optional in that case
|
||||||
|
@ -406,6 +417,7 @@ mod tests {
|
||||||
// [test] TODO: check the transaction data
|
// [test] TODO: check the transaction data
|
||||||
|
|
||||||
assert_eq!(real_decode.get_size(), segwit_block.len());
|
assert_eq!(real_decode.get_size(), segwit_block.len());
|
||||||
|
assert_eq!(real_decode.get_strippedsize(), 4283);
|
||||||
assert_eq!(real_decode.get_weight(), 17168);
|
assert_eq!(real_decode.get_weight(), 17168);
|
||||||
|
|
||||||
assert!(real_decode.check_witness_commitment());
|
assert!(real_decode.check_witness_commitment());
|
||||||
|
|
|
@ -429,6 +429,39 @@ impl Transaction {
|
||||||
self.get_scaled_size(1)
|
self.get_scaled_size(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the "vsize" of this transaction. Will be `ceil(weight / 4.0)`.
|
||||||
|
#[inline]
|
||||||
|
pub fn get_vsize(&self) -> usize {
|
||||||
|
let weight = self.get_weight();
|
||||||
|
(weight + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the size of this transaction excluding the witness data.
|
||||||
|
pub fn get_strippedsize(&self) -> usize {
|
||||||
|
let mut input_size = 0;
|
||||||
|
for input in &self.input {
|
||||||
|
input_size += 32 + 4 + 4 + // outpoint (32+4) + nSequence
|
||||||
|
VarInt(input.script_sig.len() as u64).len() +
|
||||||
|
input.script_sig.len();
|
||||||
|
}
|
||||||
|
let mut output_size = 0;
|
||||||
|
for output in &self.output {
|
||||||
|
output_size += 8 + // value
|
||||||
|
VarInt(output.script_pubkey.len() as u64).len() +
|
||||||
|
output.script_pubkey.len();
|
||||||
|
}
|
||||||
|
let non_input_size =
|
||||||
|
// version:
|
||||||
|
4 +
|
||||||
|
// count varints:
|
||||||
|
VarInt(self.input.len() as u64).len() +
|
||||||
|
VarInt(self.output.len() as u64).len() +
|
||||||
|
output_size +
|
||||||
|
// lock_time
|
||||||
|
4;
|
||||||
|
non_input_size + input_size
|
||||||
|
}
|
||||||
|
|
||||||
/// Internal utility function for get_{size,weight}
|
/// Internal utility function for get_{size,weight}
|
||||||
fn get_scaled_size(&self, scale_factor: usize) -> usize {
|
fn get_scaled_size(&self, scale_factor: usize) -> usize {
|
||||||
let mut input_weight = 0;
|
let mut input_weight = 0;
|
||||||
|
@ -857,6 +890,8 @@ mod tests {
|
||||||
"a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string());
|
"a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string());
|
||||||
assert_eq!(realtx.get_weight(), tx_bytes.len()*WITNESS_SCALE_FACTOR);
|
assert_eq!(realtx.get_weight(), tx_bytes.len()*WITNESS_SCALE_FACTOR);
|
||||||
assert_eq!(realtx.get_size(), tx_bytes.len());
|
assert_eq!(realtx.get_size(), tx_bytes.len());
|
||||||
|
assert_eq!(realtx.get_vsize(), tx_bytes.len());
|
||||||
|
assert_eq!(realtx.get_strippedsize(), tx_bytes.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -887,8 +922,24 @@ mod tests {
|
||||||
"f5864806e3565c34d1b41e716f72609d00b55ea5eac5b924c9719a842ef42206".to_string());
|
"f5864806e3565c34d1b41e716f72609d00b55ea5eac5b924c9719a842ef42206".to_string());
|
||||||
assert_eq!(format!("{:x}", realtx.wtxid()),
|
assert_eq!(format!("{:x}", realtx.wtxid()),
|
||||||
"80b7d8a82d5d5bf92905b06f2014dd699e03837ca172e3a59d51426ebbe3e7f5".to_string());
|
"80b7d8a82d5d5bf92905b06f2014dd699e03837ca172e3a59d51426ebbe3e7f5".to_string());
|
||||||
assert_eq!(realtx.get_weight(), 442);
|
const EXPECTED_WEIGHT: usize = 442;
|
||||||
|
assert_eq!(realtx.get_weight(), EXPECTED_WEIGHT);
|
||||||
assert_eq!(realtx.get_size(), tx_bytes.len());
|
assert_eq!(realtx.get_size(), tx_bytes.len());
|
||||||
|
assert_eq!(realtx.get_vsize(), 111);
|
||||||
|
// Since
|
||||||
|
// size = stripped_size + witness_size
|
||||||
|
// weight = WITNESS_SCALE_FACTOR * stripped_size + witness_size
|
||||||
|
// then,
|
||||||
|
// stripped_size = (weight - size) / (WITNESS_SCALE_FACTOR - 1)
|
||||||
|
let expected_strippedsize = (EXPECTED_WEIGHT - tx_bytes.len()) / (WITNESS_SCALE_FACTOR - 1);
|
||||||
|
assert_eq!(realtx.get_strippedsize(), expected_strippedsize);
|
||||||
|
// Construct a transaction without the witness data.
|
||||||
|
let mut tx_without_witness = realtx.clone();
|
||||||
|
tx_without_witness.input.iter_mut().for_each(|input| input.witness.clear());
|
||||||
|
assert_eq!(tx_without_witness.get_weight(), expected_strippedsize*WITNESS_SCALE_FACTOR);
|
||||||
|
assert_eq!(tx_without_witness.get_size(), expected_strippedsize);
|
||||||
|
assert_eq!(tx_without_witness.get_vsize(), expected_strippedsize);
|
||||||
|
assert_eq!(tx_without_witness.get_strippedsize(), expected_strippedsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in New Issue