This answer states that SegWit doesn't reduce transaction size. If this is true, why is it cheaper to send a SegWit transaction?
2 Answers
Segwit introduced a new limit for blocks, the blockweight limit, superseding the previous blocksize limit. Under the segwit rules, witness data is counted at a lower weighting than non-witness data towards the blockweight. Since some of the input parts have moved to the witness stack in segwit transactions, segwit transactions have less weight even though their raw byte length is similar to non-segwit transactions. Since fees are paid according to the weight (i.e. the portion of “blockspace” transactions bid on), segwit transactions are cheaper than non-segwit transaction as they have less weight.
Let's compare a 2-input and 2-output transaction for single-sig output types. I'll refer to the byte length of the transaction as "raw size", the transaction without its witness data as "stripped size", and the size-equivalent when accounting for the witness discount as "virtual size".
P2PKH – Pay to Public Key Hash has no witness data, so raw size is equal to stripped size is equal to virtual size. A P2PKH transaction with two inputs and two outputs has 374 bytes (= 374 vbytes).
P2SH-P2WPKH – Pay to Script Hash-wrapped Pay to Witness Public Key Hash (aka "wrapped segwit") locks funds to a P2SH output, but the input's redeemscript contains a witness program that redirects the evaluation to the witness stack. The content of the witness stack is the same as a P2PKH
scriptSig
. A P2SH-P2WPKH transaction with two inputs and two outputs has a raw size of 420 bytes, a stripped size (removing witness data) of 202 bytes, and a virtual size of 256.5 vbytes.P2WPKH – Pay to Witness Public Key Hash (aka single-sig v0 native segwit) does not need the P2SH indirection, but directly resolves a witness program. It has the same witness stack as a P2SH-P2WPKH input. A P2WPKH transaction with two inputs and two outputs has a raw size of 372 bytes, a stripped size of 154 bytes and a virtual size of 208.5 vbytes.
P2TR – Pay to Taproot (v1 native segwit (keypath-spend)) also directly resolves a witness program. Since the witness program already contains a public key instead of a pubkey hash, the witness stack is smaller by the public key, but the output script is larger. A P2TR transaction with two inputs and two outputs has a raw size of 312 bytes, a stripped size of 178 bytes, and a virtual size of 211.5 vbytes.
The raw size corresponds to the data footprint of the transaction on disk or the bandwidth cost to transmit it. We see that P2SH-P2WPKH is actually the biggest in raw size by a margin. P2WPKH and P2PKH are very close to each other in raw size with the legacy format P2PKH being slightly smaller in input size, but slightly bigger in output size. P2TR has the smallest data footprint.
The virtual size corresponds to the blockweight which determines the fees and how many transactions can fit in a block. After applying the weighting that the witness is subject to, P2WPKH has the smallest weight, closely followed by P2TR, followed by P2SH-P2WPKH and the legacy format P2PKH counts as the heaviest.
Size calculations
Transaction headers list the transaction version (4 B), the count of inputs (VarInt, usually 1 B, but up to 9 B), the count of outputs (varInt, usually 1 B, but up to 9 B), and the locktime (4 B). For segwit transactions, we add a witness marker (1 WU) and a witness flag (1 WU) that pertain to the whole transaction.
Every input must indicate the UXTO it's spending per an outpoint (txid+vout = 32+4 B), have a sequence value (4 B), and have an input script (scriptSig
). For non-segwit output types, the scriptSig
contains script arguments and/or a redeemscript to satisfy the output script (scriptPubKey
). For wrapped segwit inputs, the scriptSig
consists of a redeemscript that contains a witness program which redirects to the Witness Stack as the final script. For native segwit outputs, the scriptSig
is empty which is indicated by a scriptSig
length of 0. Per the segwit rules this is interpreted as a validation redirection to the Witness Stack. Note that if a transaction has at least one segwit input, there must be a Witness Stack for every input, with non-segwit inputs having a length-zero Witness Stack (i.e. just one byte to indicate the length of 0).
Outputs consist of an amount of satoshis (8 B) and an output script (scriptPubKey
). Outputs don't have witness data.
P2PKH
TxHeader: 10 B = 40 WU
Input¹: 148 B = 592 WU
Output: 34 B = 136 WU
For legacy formats, the raw size, stripped size and virtual size are all equal because they do not have witness data.
Tx with 2 inputs and 2 outputs:
raw = stripped = vsize = 10 B + 2×148 B + 2×34 B = 374 B = 374 vB
weight = 4×374 vB = 1496 WU
P2SH-P2WPKH
TxHeader: 10 B + 2 WU = 10.5 vB = 42 WU
Input²: 64 B + 108 WU = 91 vB = 364 WU
Output: 32 vB = 128 WU
Tx with 2 inputs and 2 outputs:
raw = 12 B + 2×(64 B + 108 B) + 2×32 B = 420 B
stripped = 10 B + 2×64 B + 2+32 B = 202 B
weight = 42 WU + 2×(4×64 vB + 108 WU) + 2×128 WU = 1026 WU = 256.5 vB
P2WPKH
TxHeader: 10 B + 2 WU = 10.5 vB = 42 WU
Input³: 41 vB + 108 WU = 68 vB = 272 WU
Output: 31 vB = 124 WU
Tx with 2 inputs and 2 outputs:
raw = 12 B + 2×(41 B + 108 B) + 2×31 B = 372 B
stripped = 10 B + 2×41 B + 2×31 B = 154 B
weight = 42 WU + 2×(4×41 vB + 108 WU) + 2×124 WU = 834 WU = 208.5 vB
P2TR
TxHeader: 10 B + 2 WU = 10.5 vB = 42 WU
Input⁴: 41 vB + 66 WU = 57.5 vB = 230 WU
Output: 43 vB = 172 WU
Tx with 2 inputs and 2 outputs:
raw = 12 B + 2×(41 B + 66 B) + 2×43 B = 312 B
stripped = 10 B + 2×41 B + 2×43 B = 178 B
weight = 42 WU + 2×(4×41 vB + 66 WU) + 2×178 WU = 846 WU = 211.5 vB
Details of the input script weights can be found in:
¹ How big is the input of a P2PKH transaction?
² What is the size and weight of a wrapped segwit single-sig input?
³ What is the size and weight of a P2WPKH input?
⁴ What is the weight of a P2TR input?
I compared to the following 9 types of transaction's weight. And then I found that No9 (P2WPKH => P2WPKH) was the lightest.
- Transaction patterns
// 1 transaction consists of 1 txin and 1 txout
1. (in)P2PKH => (out)P2PKH [weight = 764]
2. (in)P2PKH => (out)P2SH-P2WPKH [weight = 756]
3. (in)P2PKH => (out)P2WPKH [weight = 752]
4. (in)P2SH-P2WPKH => (out)P2PKH [weight = 541]
5. (in)P2SH-P2WPKH => (out)P2SH-P2WPKH [weight = 533]
6. (in)P2SH-P2WPKH => (out)P2WPKH [weight = 529]
7. (in)P2WPKH => (out)P2PKH [weight = 449]
8. (in)P2WPKH => (out)P2SH-P2WPKH [weight = 441]
9. (in)P2WPKH => (out)P2WPKH [weight = 437]
- Result
// I used bitcoin core rpc (v0.17.1) like createrawtransaction, signrawtransactionwithkey and decoderawtransaction.
[INPUT = P2PKH]
// P2PKH => P2PKH
"size": 191,
"vsize": 191,
"weight": 764,
// P2PKH => P2SH-P2WPKH
"size": 189,
"vsize": 189,
"weight": 756,
// P2PKH => P2WPKH
"size": 188,
"vsize": 188,
"weight": 752,
[INPUT = P2SH-P2WPKH]
// P2SH-P2WPKH => P2PKH
"size": 217,
"vsize": 136,
"weight": 541,
// P2SH-P2WPKH => P2SH-P2WPKH
"size": 215,
"vsize": 134,
"weight": 533,
// P2SH-P2WPKH => P2WPKH
"size": 214,
"vsize": 133,
"weight": 529,
[INPUT = P2WPKH]
// P2WPKH => P2PKH
"size": 194,
"vsize": 113,
"weight": 449,
// P2WPKH => P2SH-P2WPKH
"size": 192,
"vsize": 111,
"weight": 441,
// P2WPKH => P2WPKH
"size": 191,
"vsize": 110,
"weight": 437,
- Detail Result (transaction hex)
[INPUT = P2PKH]
// P2PKH => P2PKH
0200000001d0e13f4319cb8eb82cb4fae204aa92e86f4b300b86443ac6ca7b5e5713a805d5000000006a47304402203f59c75dce2657e2ea0f555bda618f60b5fc7c29d06b388a7dfb9fdd152628170220722b1395dda99e3b09e45937ae768298ba337fe825e9bf799cf84e69b09c31420121034f40428cabea81e7e1f0c7bc11fc4cfff4c22136205d9fde14bce2de34c3c0b0ffffffff01c0e4022a010000001976a9148329298662e6202d231b1a060c9c31740f1abf0088ac00000000
// P2PKH => P2SH-P2WPKH
0200000001d0e13f4319cb8eb82cb4fae204aa92e86f4b300b86443ac6ca7b5e5713a805d5000000006a473044022063141301b08eebcd69fbbf0c9247c43f9bf5294e0f01bfb2da6630cbd4ca0e0802207595dd76e04fe3ba8b74ff82802cd6dd9083438b32ca180349e847ce16272b240121034f40428cabea81e7e1f0c7bc11fc4cfff4c22136205d9fde14bce2de34c3c0b0ffffffff01c0e4022a0100000017a9149900febf4619963e50167e4e8574d66e5b5066218700000000
// P2PKH => P2WPKH
0200000001d0e13f4319cb8eb82cb4fae204aa92e86f4b300b86443ac6ca7b5e5713a805d5000000006a47304402206329cb55c7bc23bb5f0a610d4aac24ced6bd97ace9ee657f5f7f278a2e55b05002204f9b1329dbea5249e1190414963a78af7bd764cfddf7826cb5a8e908a39e787b0121034f40428cabea81e7e1f0c7bc11fc4cfff4c22136205d9fde14bce2de34c3c0b0ffffffff01c0e4022a01000000160014265d42333ea7c83b142cbc3f5e90618f2815b97400000000
[INPUT = P2SH-P2WPKH]
// P2SH-P2WPKH => P2PKH
02000000000101ff516fbcb5ee39d86569b32399ba77f86d8c840a58e9c00bafe9401fac50ba8f000000001716001402e386ba4c3ab0337779e8cf53ee29be1f76e56affffffff01c0e4022a010000001976a9144bd165e45738f90715dd58c66e609e3420745c4088ac024730440220485fda83adf6674683a5dcb3640eb6fade65ff87d8b86b9ff7ad78d7ee2adda3022050901b7877f51931bd21dd042a951327974616ae80cfd045eb9daffa4e3d3a160121032fd7684e4355ea5bb5d690b36177ef0c476031f776b5207aaed8c6f2773dccf500000000
// P2SH-P2WPKH => P2SH-P2WPKH
02000000000101ff516fbcb5ee39d86569b32399ba77f86d8c840a58e9c00bafe9401fac50ba8f000000001716001402e386ba4c3ab0337779e8cf53ee29be1f76e56affffffff01c0e4022a0100000017a914ea78eae3d8b5265a564f60a2d35c92fd80340758870247304402205768fd4a1a43377d602ab071ffd6c10e9cd653f32352734407d5f570633ec8fa02204ec4a3979318654c282122e883ea28f6f345347c771fdd5d178512a0acb3e6680121032fd7684e4355ea5bb5d690b36177ef0c476031f776b5207aaed8c6f2773dccf500000000
// P2SH-P2WPKH => P2WPKH
02000000000101ff516fbcb5ee39d86569b32399ba77f86d8c840a58e9c00bafe9401fac50ba8f000000001716001402e386ba4c3ab0337779e8cf53ee29be1f76e56affffffff01c0e4022a01000000160014795fe27ac90977d005752d76c9b37e0f4709107c0247304402202cf3cc0567f2b4cdc095ba4de1b450bb09e4fe6e8a7e5a9fae2bffd0e200c2350220257ce6193a87b6addcb44fca4245f38ab4470ee8149207460d2712336948cce80121032fd7684e4355ea5bb5d690b36177ef0c476031f776b5207aaed8c6f2773dccf500000000
[INPUT = P2WPKH]
// P2WPKH => P2PKH
02000000000101a33652b7a2408b854878dbf2936b2a29208267d7b747d3b9d6d52aea894c329e0000000000ffffffff01606b042a010000001976a9146626b697454680b06e3c0e2d07272137a97e8be188ac0247304402203c6b03fdb2b5a6b12820bc420af9c0f35d96100aff02b93b9f05d389d1b0f200022059bb8a679febe999216f510149047413dac4b49f6e0d3aa9ef33853141815c2f01210242586c4ad4cb0d7fbe0ecfe902024f8f1581564f8f257a7cc52bf26275283ed200000000
// P2WPKH => P2SH-P2WPKH
02000000000101a33652b7a2408b854878dbf2936b2a29208267d7b747d3b9d6d52aea894c329e0000000000ffffffff01606b042a0100000017a9141548a74c39bf89a83812613bc0e65a933c7e10df870247304402207ed9314ec843a98acd21260760c93418303f25f46ff6861cdc751ce49381988f02203f41929d6668b64b98da22a871ff9d968ab08cf7b81e221f1fc957355c442b5201210242586c4ad4cb0d7fbe0ecfe902024f8f1581564f8f257a7cc52bf26275283ed200000000
// P2WPKH => P2WPKH
02000000000101a33652b7a2408b854878dbf2936b2a29208267d7b747d3b9d6d52aea894c329e0000000000ffffffff01606b042a01000000160014d1c5773209f4b660714ea92e1aa6d5b0338a68aa0247304402205a94a9e82f19d96868ab20d44aa3c0c50b66e103ac36868b3c8c31455b95479e02207200f59dcc0d7745c1524371ed0ff1d49e7df3c30d5416fe9589fd180bd471ed01210242586c4ad4cb0d7fbe0ecfe902024f8f1581564f8f257a7cc52bf26275283ed200000000
- I think..
The current maximum allowed weight for a block is 4MB. Miners consider fee(in satoshi) per weight of each transaction in order to maximize their profit.
https://github.com/bitcoin/bitcoin/blob/master/src/consensus/consensus.h#L15