Weight units
Weight units are a measurement used to compare the size of different Bitcoin transactions to each other in proportion to the consensus-enforced maximum block size limit. Weight units are also used to measure the size of other block chain data, such as block headers. As of Bitcoin Core 0.13.0 (released August 2016)[1], each weight unit represents 1/4,000,000th of the maximum size of a block.
Virtual size (vsize), also called virtual bytes (vbytes), are an alternative measurement, with one vbyte being equal to four weight units. That means the maximum block size measured in vsize is 1 million vbytes.
History
Bitcoin was released with an implicit maximum block size limit of 32 mibibytes (32 MiB), which was the maximum allowed size of a P2P protocol block message.[2] Effective block 79,400 (7 September 2010), this became an explicit limit of 1 megabyte (1 MB).[3]
In both cases, to calculate how much a transaction or other data counted towards these maximum block size limits, you simply put the data in the format used by the P2P protocol's block message and counted the bytes.
The introduction of a soft-fork segregated witness (segwit) idea in late 2015[4] meant that the transaction format could be extended with new fields that would be excluded from the historic block size limits—allowing an increase in the maximum block size. But that increase was only possible in a soft fork if the new fields contributed less towards the maximum block size than the fields in the original transaction format.
Although some people complained about that being unfair[5], many Bitcoin Protocol developers considered discounting the new fields to be advantageous.[6][7] The new fields store witnesses, which are transaction signatures and other data necessary to authenticate the spender of certain bitcoins. Witnesses do not need to be stored by all full nodes after they are processed, unlike other parts of a transaction, so they have less effect on the cost of node operation and (arguably) warrant a discount.
This introduction of a discount for certain fields in certain transactions lead to the development of the weight unit which allows easy comparison between transactions that contain the discounted fields and those that don't. Weight units were designed to be fully backwards compatible with all previous versions of Bitcoin Core even though blocks created after segwit activated may include up to almost four times as much data as they could previously.
For backwards compatibility with software using the earlier bytes metric[8], virtual size (vsize) was introduced. A unit of vsize is equal to four weight units. Some developers call a unit of vsize by the name of vbyte[9] because the number of bytes and vbytes in a transaction are identical for legacy transactions.
Weight for legacy transactions
Transactions that don't use segregated witness (segwit) are currently called legacy transactions. For these transactions, calculating the number of weight units in a transaction is as easy as putting the transaction into the format used in a P2P protocol block message, counting the number of bytes, and multiplying by four.
For example, at the time of writing (January 2018), the most commonly seen transaction template in the block chain is a legacy transaction with one input (using P2PKH with a compressed pubkey) and two P2PKH outputs, or about 226 bytes. Here's a byte map of that transaction template:
To change from bytes to weight units, we simply scale everything up by a factor of four:
At 904 weight, to include the above transaction in a block consumes 0.0226% of the available maximum block space.
To convert from weight units to vbytes, divide the total by four. For legacy transactions, this means that vbytes are equal to bytes.
Weight for segwit transactions
Transactions that use segregated witnesses are called segwit transactions. For these transactions, calculating the number of weight units in a transaction is more complicated.
- The transaction is put into the format used by a P2P protocol block message (segwit-enabled)
- Each byte of the segwit marker, flag, and witness fields counts as one weight unit
- Each byte of the other fields in the transaction counts as four weight units
For example, the segwit equivalent to the P2PKH transaction analyzed in the legacy section above would be a transaction with one input (using P2WPKH) and two P2WPKH outputs, or about 222 bytes. Here's a byte map of that transaction template with the segwit-specific fields highlighted in blue:
To change from bytes to weight units, we use the method described above where the highlighted fields stay the same size but the other fields are multiplied by four. When displayed at the same scale, this makes it appear that the segwit fields have shrunk:
At 561 weight units, to include the above transaction in a block consumes 0.014025% of the available maximum block space, a 61% reduction compared to the equivalent legacy transaction described previously. The exact amount of space saved by converting from legacy transactions to segwit transactions will vary depending on various transaction details.
To convert from weight units to vbytes, divide by four. For the example transaction above, this makes the transaction 140.25 vbytes. Note that fractional vbytes are possible, but they may not be compatible with legacy applications that expect only integer values, so it is recommended[10] to round up. For example, Bitcoin Core reports this transaction as having a vsize of 141 vbytes.
Misconceptions
Possibly because of the vbytes metric, it is a common misconception that segwit somehow makes transactions much smaller—but this is incorrect. A 300-byte transaction is 300 bytes on-disk and over-the-wire. Segwit just counts those bytes differently toward the maximum block size of 4M weight units.
The maximum size of a block in bytes is nearly equal in number to the maximum amount of block weight units, so 4M weight units allows a block of almost 4M bytes (4MB). This is not a somehow "made-up" size; the maximum block size is really almost 4MB on-disk and over-the-wire. However, this maximum can only be reached if the block is full of very weirdly-formatted transactions, so it should not usually be seen.
The typical size of a block depends on the make-up of transactions in that block. As of 2017, the average transaction make-up would lead to blocks with 4M weight units being about 2.3MB in size if all transactions were segwit transactions.
Detailed example
Consider this transaction:
0100000000010115e180dc28a2327e687facc33f10f2a20da717e5548406f7ae8b4c8 11072f85603000000171600141d7cd6c75c2e86f4cbf98eaed221b30bd9a0b928ffff ffff019caef505000000001976a9141d7cd6c75c2e86f4cbf98eaed221b30bd9a0b92 888ac02483045022100f764287d3e99b1474da9bec7f7ed236d6c81e793b20c4b5aa1 f3051b9a7daa63022016a198031d5554dbb855bdbe8534776a4be6958bd8d530dc001 c32b828f6f0ab0121038262a6c6cec93c2d3ecd6c6072efea86d02ff8e3328bbd0242 b20af3425990ac00000000
Data | Description | Raw byte count | Type (multiplier) | Section total weight | Running total weight |
---|---|---|---|---|---|
01000000 | Version 1 | 4 | Non-witness (4x) | 16 | 16 |
00 | SegWit marker | 1 | Witness (1x) | 1 | 17 |
01 | SegWit flag | 1 | Witness (1x) | 1 | 18 |
01 | Number of inputs (1) | 1 | Non-witness (4x) | 4 | 22 |
15..56 | Previous output hash | 32 | Non-witness (4x) | 128 | 150 |
03000000 | Previous output index (3) | 4 | Non-witness (4x) | 16 | 166 |
17 | Script length (23 bytes) | 1 | Non-witness (4x) | 4 | 170 |
16..28 | Script: P2SH-enclosed P2WPKH witness program | 23 | Non-witness (4x) | 92 | 262 |
ffffffff | Sequence | 4 | Non-witness (4x) | 16 | 278 |
01 | Output count (1) | 1 | Non-witness (4x) | 4 | 282 |
9caef50500000000 | Output value (0.99987100 BTC) | 8 | Non-witness (4x) | 32 | 314 |
19 | Output script size (25) | 1 | Non-witness (4x) | 4 | 318 |
76..ac | Script: DUP HASH160 0x1d7c... EQUALVERIFY CHECKSIG | 25 | Non-witness (4x) | 100 | 418 |
02 | Number of stack items for input 0 (2) | 1 | Witness (1x) | 1 | 419 |
48 | Size of stack item 0 (72) | 1 | Witness (1x) | 1 | 420 |
304...ab01 | Stack item 0, signature | 72 | Witness (1x) | 72 | 492 |
21 | Size of stack item 1 (33) | 1 | Witness (1x) | 1 | 493 |
03..ac | Stack item 1, pubkey | 33 | Witness (1x) | 33 | 526 |
00000000 | Locktime (0) | 4 | Non-witness (4x) | 16 | 542 |
The transaction's real size on disk and over the network is 218 bytes, which is the size in bytes of the whole transaction expressed above in hexadecimal. The weight is always greater than the real size, in this case 542 weight units. The size in vbytes would be 135.5.
References
- Bitcoin Core 0.13.0 release notes
- Earliest known Bitcoin code,
src/main.h:17
, Satoshi Nakamoto (attributed), November 2008 (published 10 March 2012) - Bitcoin commit 8c9479c, Satoshi Nakamoto, 7 September 2010
- Segregated witness and its impact on scalability (presentation video), Pieter Wuille, 2015-12-07
- SegWit tx is unfairly cheap, Jihan Wu, Twitter.com, 2017-05-27, retrieved 2017-01-17
- What is behind the segwit discount?, Segwit.org, 2017-01-10, retrieved 2021-03-01
- Why a discount factor of 4?, Segwit.org, 2017-01-13, retrieved 2021-03-01
- The advantage of using vsize..., Pieter Wuille, Bitcoin.StackExchange.com, 2017-08-09, retrieved 2017-01-17
- PSA: Wrong fee rates on block explorers, Mark Erhardt, 2017-12-12, retrieved 2017-01-17
- Segwit wallet dev guide: fee estimation, BitcoinCore.org contributors, BitcoinCore.org, retrieved 2018-01-17