In an Optech newsletter, size is referred to using vbytes. Is there a difference between vbytes and bytes? If so, what is the difference?
Yes, bytes and vbytes are referring to two different metrics: size and virtual size (vsize).
The size in [bytes] of a transaction refers to the raw byte length of its serialized format. It is used to measure the data footprint of transactions when relayed on the network or stored on disk.
The vsize in [vbytes] refers to a transaction's weighted size under segwit's rules. It is used to compare how much blockweight needs to be allocated to confirm a transaction.
Block weight limit
Bitcoin blocks are limited in their transaction capacity. Before Segregated Witness (segwit) was activated, blocks were limited to a blocksize of 1,000,000 bytes. Under that paradigm, the size of a transaction corresponded to the byte count of its serialized format.
The activation of the segwit softfork replaced the blocksize limit with a blockweight limit of 4,000,000 [weight units (wu)]. The new protocol rule defines the weight of a transaction as the sum of the witness bytes counted at a factor of one and non-witness bytes counted at a factor of four.
weight [wu] = 4 [wu/B] × non-witness length [B] + 1 [wu/B] × witness length [B]
Since non-segwit transactions don't have any witness data, this results in equivalent rules for non-segwit blocks before and after the rule change:
1 B / 1,000,000 B = 4 wu / 4,000,000 wu
One byte is the same portion of the previous blocksize limit as four weight units of the new blockweight limit. Transactions without witnesses, non-segwit transactions, take exactly the same portion of the blockweight as they took of the blocksize prior to segwit activation. This allowed segwit to be introduced as a forward compatible soft fork.
For segwit transactions, which do include witness data, the resulting transaction weight is strictly smaller than
4 × size due to the witness bytes contributing at a lower factor. This results in a lower relative portion of the blockweight to include a segwit transactions than an equivalent non-segwit transaction. The adoption of the segwit output format results in an effective capacity increase. Segwit blocks may exceed raw byte sizes of 1,000,000 bytes, with e.g. the biggest block to date achieving a raw byte size 2,424,027 bytes.
Feerates and their units
Before segwit activated, users measured transaction sizes in [bytes] and feerates in [satoshis per byte]. Since segwit activated, the protocol measures transactions by weight in [weight units]. At the protocol level, this shifts the range of feerate values by a factor of four.
Segwit introduces the measure virtual size (vsize) in [virtual bytes (vbytes)] to ease comparison of feerates before and after segwit activation. The
vsize is calculated by dividing the transaction weight by four:
vsize [vB] = weight [wu] / 4.
The range of values of
fee per vsize thus matches the range of the pre-segwit
fee per size. To this day (Oct 2020), it remains popular to track feerates in [satoshis per vbyte].
If you are looking for an approachable example, check out this detailed comparison with concrete values: How do virtual size, stripped size and raw size compare between legacy address formats and native segwit?
For non-segwit transactions, vbytes = bytes.
With the implementation of SegWit, we now see the weight of the block/transactions rather than seeing the absolute size on the wire. While calculating the weight of a transaction, we use a weight of four for the normal transaction components (ex signature) and weight of one for the witness components. Now vbyte is always equal to weight/4.
Following will the calculation to distinguish between vbytes and actual bytes on the wire. Let St the number of bytes needed to serialize the transaction in legacy format (which does not include the witnesses) and Sw be the number of bytes needed to serialize the witness component.
Weight of the transaction = St*4 + Sw
vbytes = (St*4 + Sw)/4 = St + Sw/4
actual size on wire = St + Sw
difference = (3/4)*Sw
Since non-SegWit transactions do not segregate the signatures to the witness component Sw = 0, and hence vbyte is equal to normal bytes.