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, they are referring to two different metrics: virtual size (vsize) and size.
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 rules. It is used to compare how much blockspace 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 4 weight units of the new blockweight limit. 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 cost of including segwit transactions in blocks compared to equivalent non-segwit transactions, which in turn 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,377,364 bytes.
When segwit activated, users commonly referred to transaction sizes in [bytes] and fee rates in [satoshis per byte] even though the protocol measured transactions by weight in [weight units] from that point on.
Virtual size measured in [vbytes] was introduced to easily compare transaction weights to the transaction sizes everyone was used to. The
vsize is calculated by dividing the transaction weight by four and rounding up:
vsize [vB] = ⌈weight [wu] / 4⌉
For a detailed comparison of concrete figures, see 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.