Implement Block.get_strippedsize() and Transaction.get_vsize()#626
Implement Block.get_strippedsize() and Transaction.get_vsize()#626dr-orlovsky merged 6 commits intorust-bitcoin:masterfrom
Block.get_strippedsize() and Transaction.get_vsize()#626Conversation
TheBlueMatt
left a comment
There was a problem hiding this comment.
What's the specific use-case for this? I honestly can't think of a use for the stripped size of anything now that basically every part of bitcoin supports segwit.
|
|
||
| /// Gets the "vsize" of this transaction. Will be `ceil(weight / 4.0)`. | ||
| #[inline] | ||
| pub fn get_vsize(&self) -> usize { |
There was a problem hiding this comment.
Why do we need to expose this? Users can just divide-rounding-up themselves, and I'm not sure how much users should/do have a use for this?
There was a problem hiding this comment.
tx.get_vsize() is readable and handy. Any reason for the user not to use such this instead of comming up with their own version?
src/blockdata/transaction.rs
Outdated
| #[inline] | ||
| pub fn get_vsize(&self) -> usize { | ||
| let weight = self.get_weight(); | ||
| (weight / WITNESS_SCALE_FACTOR) + if weight % WITNESS_SCALE_FACTOR == 0 { 0 } else { 1 } |
There was a problem hiding this comment.
The usual (and more efficient) way to divide-rounding-up is to add one minus the divisor and then divide, instead of branching.
There was a problem hiding this comment.
Thanks for a comment. I fixed this.
src/blockdata/block.rs
Outdated
|
|
||
| /// Get the strippedsize of the block | ||
| pub fn get_strippedsize(&self) -> usize { | ||
| let txs_size: usize = self.txdata.iter().map(|tx| { |
There was a problem hiding this comment.
Yes, I think we should expose a utility in transaction to get the stripped size, it would simplify this and may have value itself.
sgeisler
left a comment
There was a problem hiding this comment.
utACK 2085dc3
The tests seem good, I checked the stripped size and vsize that differ from the normal size against bitcoind.
@TheBlueMatt if it's in bitcoin core RPC replies then it's probably also ok to include it in rust-bitcoin imo.
|
`Block.get_strippedsize()` is also simplified and optimized.
I don't think this is a good argument for doing anything. Bitcoin Core has lots of backwards compatibility concerns and ultimately are just developers, like us. Whether they decided to add anything or not isn't something above question.
Now that's a use-case! Given this is quite simple it seems reasonable to add it for something like this. |
| } | ||
|
|
||
| /// Gets the size of this transaction excluding the witness data. | ||
| pub fn get_strippedsize(&self) -> usize { |
There was a problem hiding this comment.
Can you add a test with a few sample transactions where you call get_strippedsize on the original transaction, then remove the witness, then check that the new vsize/weight/size methods all return the same as the original strippedsize (mod multipliers).
There was a problem hiding this comment.
I don't think it is needed because test_nonsegwit_transaction() covers this, but I added this in cdf7be4.
| 80 + VarInt(self.txdata.len() as u64).len() | ||
| } | ||
|
|
||
| /// Get the size of the block |
There was a problem hiding this comment.
Nit: this may be #[inline] (but do not discard ACKs b/c of just this)
| } | ||
|
|
||
| /// Get the strippedsize of the block | ||
| pub fn get_strippedsize(&self) -> usize { |
There was a problem hiding this comment.
| pub fn get_strippedsize(&self) -> usize { | |
| pub fn get_stripped_size(&self) -> usize { |
just to be consistent with other function names?
| } | ||
|
|
||
| /// Gets the size of this transaction excluding the witness data. | ||
| pub fn get_strippedsize(&self) -> usize { |
|
I do not think my nits worth discarding existing reviews. Merging now (3 ACKs) and feel free to propose post-merge PR with these nit fixed, if you'd like to. |
|
Thank you for merging my PR! |
darosior
left a comment
There was a problem hiding this comment.
Sorry for seeing this only now. The get_vsize transaction isn't correct as per Bitcoin Core's definition [0]. We already have a correct one in src/policy:
rust-bitcoin/src/policy/mod.rs
Lines 57 to 61 in 72dbe1d
Sure, we could assume that users don't actually need the sigop-aware version if they are not going to craft clumsy transactions but:
get_vsizecould just callget_virtual_tx_size- we could at least document the divergence
[0] Arguably there is both a BIP141 and a Core definition, and it's correct as per the former
|
@darosior thanks for spotting. Probably we need a dedicated issue? |
|
@dr-orlovsky opened a PR directly going for the simplest alternative: just document the behaviour divergence |
I implemented the following methods:
block.get_strippedsize(): gets the "strippedsize" of a block.tx.get_vsize(): gets the "virtual" size of a transaction.The test values added for this code match the values comes from Bitcoin Core.
Edit:
block.get_strippedsize()will calltx.get_scaled_size()twice for every transactions in a block, which cannot be prevented without exposing an extra function inTransactionwhich produces the non-segwit data bytes. This will impact the performance, while the exposed API kept simple.Edit 2: If you prefer performance over smaller API change, let me know. I will modify my PR (will add
tx.get_strippedsize()).