10

This answer states that SegWit doesn't reduce transaction size. If this is true, why is it cheaper to send a SegWit transaction?

1

2 Answers 2

22

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".

Table showing the detailed data

  • P2PKHPay 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-P2WPKHPay 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.

  • P2WPKHPay 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.

  • P2TRPay 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 weighing 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?

0
2

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

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.