Author

Topic: How to calculate transaction Size (vbytes) for Segwit Addresses (Read 452 times)

legendary
Activity: 2352
Merit: 6089
bitcoindata.science
P2SH covers a wide range of scripts, from a single byte OP_TRUE to 520 byte maximum length allowed to be pushed as redeem script raw bytes. you can't come up with a formula only based on the script being P2SH. it has to be based on the redeem script.

in these two cases the redeem script shows that this is of type P2SH-P2WPKH so we have as witness:
- one signature (fixed 71 bytes if the wallet grinds for low r values)
- length of signature 1 byte
- one compressed public key (33 bytes)
- length of public key 1 byte
- witness stack item count 1 byte
we have as signature script:
- a redeem script of size 23
- push size will be 1
that means each input adds 32(hash)+4(index)+24(sigScr)+4(sequence) = 64 bytes & 71+1+33+1+1=107 as witness
each output that has P2SH (like the first example) adds 8(amount)+23(pubScr)+1(length)=32 bytes
each transaction has some extra bytes: 4(version)+1(inCount)+1(outCount)+4(locktime)=10 & 2(segwit flag)

so the raw bytes or the total size is (2*64)+(2*107)+(2*32)+10+2=418
base size (without witnesses) is (2*64)+(2*32)+10=202
weight is base*3 + totalsize = 1,024
virtual size is weight/4 = 256
fee is 279541 satoshi => 279541/256=1,091.95703125 =~1,092 sat/vbyte

wiggle room
if the wallet doesn't grind for low r and has to add the 0x00 to indicate positive r for high values you can add 1 byte to for high r which makes witness 108 bytes, total size 420, base size same 202, weight 1026, virtual size 257 and fee 1,088 sat/vbyte


the second link is the same with the difference in their output types which are P2WPKH instead of P2SH and each one adds 8(amount)+22(pubscr)+1(length)=31 bytes

that's very precise.
I updated the calculator with your formula and it is now working very well for those 3 address types.

It is working very well now. Let's see those last P2SH transactions that I was having problems. Using blockstream as nc50lc suggested:



I will try to make a more detailed solution so the user can select type of input during the week.

I wanna still make some prediction using mempool data.

Thank you for your help guys.
legendary
Activity: 3472
Merit: 10611
https://blockchair.com/bitcoin/transaction/a0fed665b99734467285fe379d563cebe484b96ac393519eea20e7c6cd82bd9b
418, i calculated 374bytes
the calculate fee is 0.00229866 and the paid fee is 0.00279
This is a strange result for P2SH.  I can improve here

Segwit
https://blockchair.com/bitcoin/transaction/773f472b3806a9e8b51b9406a9080fb4ae015b28814f5ecb6ce6a3d5a47818e0
589, i got 522.
Fee calculated 0.00000279 x real 0.00000346
Not very good, again P2SH  ... I am using this formula v = (42 + 272×n + 128×t)/4

P2SH covers a wide range of scripts, from a single byte OP_TRUE to 520 byte maximum length allowed to be pushed as redeem script raw bytes. you can't come up with a formula only based on the script being P2SH. it has to be based on the redeem script.

in these two cases the redeem script shows that this is of type P2SH-P2WPKH so we have as witness:
- one signature (fixed 71 bytes if the wallet grinds for low r values)
- length of signature 1 byte
- one compressed public key (33 bytes)
- length of public key 1 byte
- witness stack item count 1 byte
we have as signature script:
- a redeem script of size 23
- push size will be 1
that means each input adds 32(hash)+4(index)+24(sigScr)+4(sequence) = 64 bytes & 71+1+33+1+1=107 as witness
each output that has P2SH (like the first example) adds 8(amount)+23(pubScr)+1(length)=32 bytes
each transaction has some extra bytes: 4(version)+1(inCount)+1(outCount)+4(locktime)=10 & 2(segwit flag)

so the raw bytes or the total size is (2*64)+(2*107)+(2*32)+10+2=418
base size (without witnesses) is (2*64)+(2*32)+10=202
weight is base*3 + totalsize = 1,024
virtual size is weight/4 = 256
fee is 279541 satoshi => 279541/256=1,091.95703125 =~1,092 sat/vbyte

wiggle room
if the wallet doesn't grind for low r and has to add the 0x00 to indicate positive r for high values you can add 1 byte to for high r which makes witness 108 bytes, total size 420, base size same 202, weight 1026, virtual size 257 and fee 1,088 sat/vbyte


the second link is the same with the difference in their output types which are P2WPKH instead of P2SH and each one adds 8(amount)+22(pubscr)+1(length)=31 bytes
legendary
Activity: 2618
Merit: 6452
Self-proclaimed Genius
https://blockchair.com/bitcoin/transaction/a0fed665b99734467285fe379d563cebe484b96ac393519eea20e7c6cd82bd9b
418, i calculated 374bytes
the calculate fee is 0.00229866 and the paid fee is 0.00279
This is a strange result for P2SH.  I can improve here
I suggest you to use blockstream to check the sizes, because the actual "virtual size" of this transaction is: 256 vB

The first reference of average sizes in the OP when used is closer to the actual vB.
Examples:

By the way, miners, BitcoinCore, Electrum, etc. will compute the fee rate based from the virtual size not raw size, so your calculator should too;
and add a lightning invoice option to your site's donation link   Wink
legendary
Activity: 2352
Merit: 6089
bitcoindata.science
i think you should also enable editing the fee textbox (1 sat/byte) and bind it with the scrollbar in a two-way mode so that the fee can be written in it instead of only showing up a the slider moves.

I changed it to a input text box, easier than making a two-way slider for now...



I made a few tests comparing my tool with random transactions:

https://blockchair.com/bitcoin/transaction/95d6566730402863e05d2ba37a74bbee7a0ed534769e92382ada4ad2e6cab05a
961 bytes, I calculated 966
Legacy transaction, everything OK


https://blockchair.com/bitcoin/transaction/79f6400e96691c319aa454e483971f5e4063ec5dbb1068912159ab8431fc6657
Legacy, everything ok
779, caculated 784


https://blockchair.com/bitcoin/transaction/a0fed665b99734467285fe379d563cebe484b96ac393519eea20e7c6cd82bd9b
418, i calculated 374bytes
the calculate fee is 0.00229866 and the paid fee is 0.00279
This is a strange result for P2SH.  I can improve here

Segwit
https://blockchair.com/bitcoin/transaction/773f472b3806a9e8b51b9406a9080fb4ae015b28814f5ecb6ce6a3d5a47818e0
589, i got 522.
Fee calculated 0.00000279 x real 0.00000346
Not very good, again P2SH  ... I am using this formula v = (42 + 272×n + 128×t)/4


Native Segwit
https://blockchair.com/bitcoin/transaction/fd6a1dbb50bfcceac73b6478bfefa363b6ae5de0e07ef8dbcaa3d1ffaf22dc1a
0.00002946 BTC fee , calculated 0.00002895 (see fee per vbyte)
size 974 calculate 966


I am having problems with P2SH  addresses. Do you have any suggestion?
I will make another formula for those.
legendary
Activity: 3472
Merit: 10611
That is exactly what those sites I mentioned did. However, as i said, they are confused for common people to use. I am thinking about a tool the common bitcoin user would be able to use and understand, even thought it is not 100% accurate.
well sometimes it is extremely hard if not impossible to be both easy to understand and correct at the same time. sometimes we can't have both and oversimplifying could be worse (misleading) if we are not careful.
what i think you could do is to add explanations or examples to all those types. for example when you say P2PKH add a info tooltip explaining the type and include an example address starting with 1.

Quote
Because even if I do everything you suggested, it would still not be accurate, because address type and number of inputs is not the only thing that has impact over transaction size.
the input/output types and their count is the only thing affecting the transaction size. there is a small wiggle room for DER signatures which you can always use the upper bound size for them to mitigate that.
legendary
Activity: 2352
Merit: 6089
bitcoindata.science

the input type is too general (legacy/segwit) and can be anything. instead it should be the actual standard scripts (aka P2PKH, P2WPKH, P2WSH, P2SH,...) and also when "script hash" comes in you could add more options to "special" scripts such a multi sig (1of2, 2of2,...), locktime,... or it could open up 2 new text boxes asking for 1) number of signatures required and 2) size of the redeem script so that it remains more general (eg. a conditional script with OP_IFs could use this option).

similarly the output count should also be specific to the type of the output being created. eg. P2WPKH outputs are 22 bytes while P2WSH outputs are 34 bytes (writing from memory, needs verification) and so on.

i think you should also enable editing the fee textbox (1 sat/byte) and bind it with the scrollbar in a two-way mode so that the fee can be written in it instead of only showing up a the slider moves.

That is exactly what those sites I mentioned did. However, as i said, they are confused for common people to use. I am thinking about a tool the common bitcoin user would be able to use and understand, even thought it is not 100% accurate.

Because even if I do everything you suggested, it would still not be accurate, because address type and number of inputs is not the only thing that has impact over transaction size.

In a few days I will add a mempool graphic and suggest a fee to get confirmed within X blocks, using a less conservative fee (lower fee) than most of those websites estimate.

I can add some different type of inputs/outputs, i agree. The formula is, for now, too general.
legendary
Activity: 3472
Merit: 10611
feel free to take a look. It is not ready yet, still under construction. I just used two calculations based in Legacy or Segwit addresses. I will try to improve it. And then work in mempool data and fee estimation:

https://bitcoindata.science/bitcoin-fee-size-calculator.html

the input type is too general (legacy/segwit) and can be anything. instead it should be the actual standard scripts (aka P2PKH, P2WPKH, P2WSH, P2SH,...) and also when "script hash" comes in you could add more options to "special" scripts such a multi sig (1of2, 2of2,...), locktime,... or it could open up 2 new text boxes asking for 1) number of signatures required and 2) size of the redeem script so that it remains more general (eg. a conditional script with OP_IFs could use this option).

similarly the output count should also be specific to the type of the output being created. eg. P2WPKH outputs are 22 bytes while P2WSH outputs are 34 bytes (writing from memory, needs verification) and so on.

i think you should also enable editing the fee textbox (1 sat/byte) and bind it with the scrollbar in a two-way mode so that the fee can be written in it instead of only showing up a the slider moves.
legendary
Activity: 2352
Merit: 6089
bitcoindata.science
formulas like this are very primitive and only work for a handful of very special cases.

They are not 100%, but the combination of a few formulas for different kind of addresses may give a good idea of how much someone will spend in a transaction. I am not planning to make raw transactions, but to estimate tx size. And then estimate fees using mempool data. Most of those websites that make fee estimation overestimate fees. I will try to give something more precise in fee estimation. I found some nice mempool API already.


feel free to take a look. It is not ready yet, still under construction. I just used two calculations based in Legacy or Segwit addresses. I will try to improve it. And then work in mempool data and fee estimation:

https://bitcoindata.science/plot-your-transaction-in-mempool.html
legendary
Activity: 3472
Merit: 10611
I want to make a tool to calculate transaction size for bitcoin transactions.
I already made for legacy addresses, using the formula below:

Code:
(number of inputs)*146+(number of outputs)*34+10

formulas like this are very primitive and only work for a handful of very special cases.
if you want to create an accurate tool then you must first fully understand the transaction structure to know what each part of it is, how they are defined and how they change. i'd start from the protocol doc from bitcoin wiki that @nc50lc posted.

for example if you have a simple byte[] to be pushed to stack like in common P2(W)PKH scripts your push size is 1 byte but if it is bigger (like in multisig redeem script) then it would be 2 bytes. the signatures could also be variable lengths depending on the wallet used to sign them, that could add up to 2 more bytes to each sig. etc.
these may not seem like much but if there were more inputs/outputs they could sum up to a bigger value. and for instance if fee was being set to the minimum amount you'll end up paying less than minrelayfee and have your tx rejected by majority of nodes.
legendary
Activity: 2618
Merit: 6452
Self-proclaimed Genius
This example doesn't really show how are those bytes calculated and how they vary.
For example, does output value always have 8 bytes? Can I just sum those data and their raw byte count as fixed, except for inputs/outputs/ and some other fields?
Here's the protocol documentation that explains that: https://en.bitcoin.it/wiki/Protocol_documentation#tx
As you can see, most of them may vary so you can only get the average if your tool wont examine the actual raw transaction.

That's if you want your tool to be as accurate as possible.
But if you'll stick to your P2PKH transaction size formula's format, you can use the first reference's approximate sizes.
legendary
Activity: 2352
Merit: 6089
bitcoindata.science
But how do I calculate Base Transaction size?? How do I get the size of the transaction "serialised with the witness data stripped"?
You need to find which parts of the transaction are "Witness data", do not count them to get the "base transaction size".
this page has the information you need: https://en.bitcoinwiki.org/wiki/Block_weight#Detailed_example

I see the problem is more complex than I originally thought. I thought, at first, that all bitcoin transaction costs vary only according to the number of inputs/outputs, fee per byte, and address type.

But there are other things that can impact transaction costs, which are not clear for me now.

This example doesn't really show how are those bytes calculated and how they vary.
For example, does output value always have 8 bytes? Can I just sum those data and their raw byte count as fixed, except for inputs/outputs/ and some other fields?


Edit:
I was able to find this guide, which gave a good aproximation:
https://bitzuma.com/posts/making-sense-of-bitcoin-transaction-fees/
Quote
Combining this defintion for size (s) with the one for weight (w) yields the following estimate for the virtual size of a P2WPKH transaction:

v = (42 + 272×n + 128×t)/4

For example, a one-input, one-output P2WPKH transaction would have a virtual size of 111 bytes. This represents a savings of 42% over the corresponding P2PKH transaction (193 bytes).
legendary
Activity: 2618
Merit: 6452
Self-proclaimed Genius
But how do I calculate Base Transaction size?? How do I get the size of the transaction "serialised with the witness data stripped"?
You need to find which parts of the transaction are "Witness data", do not count them to get the "base transaction size".
this page has the information you need: https://en.bitcoinwiki.org/wiki/Block_weight#Detailed_example
legendary
Activity: 2352
Merit: 6089
bitcoindata.science
I want to make a tool to calculate transaction size for bitcoin transactions.
I already made for legacy addresses, using the formula below:

Code:
(number of inputs)*146+(number of outputs)*34+10

I am satisfied with the results for Legacy addresses.

However I am having problems calculating the transaction size in vbytes for segwit addresses.
I was looking for BIP 141 documentation and found the formula for transaction size in Segwit addresses and found that:

Quote
Transaction size calculations
Transaction weight is defined as Base transaction size * 3 + Total transaction size (ie. the same method as calculating Block weight from Base size and Total size).

Virtual transaction size is defined as Transaction weight / 4 (rounded up to the next integer).

Base transaction size is the size of the transaction serialised with the witness data stripped.

Total transaction size is the transaction size in bytes serialized as described in BIP144, including base data and witness data.
https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#transaction-size-calculations


So, the virtual transaction size (which is what I am looking for) is Transaction weight / 4, which is the same as:
Code:
Base transaction size * 3 + Total transaction size


I found some referece on how to calculate Total Transaction size here:
Quote
Some reference numbers:

    Outputs:
        A P2PKH (1... address) output is 34 vbytes.
        A P2SH (3... address) output is 32 vbytes.
        A P2WPKH (bc1q... address of length 42) output is 31 vbytes.
        A P2WSH (bc1q... address of length 62) output is 43 vbytes.
    Inputs:
        A P2PKH spend with a compressed public key is 149 vbytes.
        A P2WPKH spend is 68 vbytes.
        A P2SH-P2WPKH spend is 93 vbytes.


But how do I calculate Base Transaction size?? How do I get the size of the transaction "serialised with the witness data stripped"?

Thanks everyone Smiley
Jump to: