3

I'm trying to calculate the weight of a 2-of-3 multisignature P2SH-P2WSH input. I found the related question Predict multi signature transaction size, which I've calculated with m=2, n=3 here:

pubkeySize=33
sigSize=72

SizeOfRedeemScript = 1+n*(1+pubkeySize)+1+1
// 2-of-3: SizeOfRedeemScript = 1+3*(1+33)+1+1 = 105

SizeOfScriptSig = 1+m*(1+sigSize)+SizeOfPushDataFor(RedeemScript)+SizeOfRedeemScript
// 2-of-3: SizeOfScriptSig = 1+2*(1+72)+2+105 = 1 + 146 + 2 + 105 = 254

sizeOf(input) = 32+4+SizeOfCsuintFor(SizeOfScriptSig) + SizeOfScriptSig + 4
// 2-of-3: sizeOf(input) = 32+4+3+254+4 = 297

The size of 2-of-3 input in P2SH has 293 to 297 bytes1. Thus, this would correspond to up to 297*4 bytes = 1188 wu.

How would I calculate the corresponding weight for a 2-of-3 multisignature P2SH-P2WSH input?


1Note that if both signatures are 71 bytes, the scriptSig is 252 bytes which as a length can be encoded in 1 byte, but in the worst case both signatures are 72 bytes and the length of the scriptSig needs 3 bytes.

2 Answers 2

3

To calculate the block weight, you need to know the size in bytes of the non-witness data and the size in bytes of the witness data.

With a P2SH-P2WSH input, your scriptSig will always be 36 bytes. This makes the size in bytes of the inputs to be 36 + 36 + 4 = 76. The witnesses contain your signatures and scripts, so the witness for that input will be 1+m*(1 + sigSize) + SizeOfVarIntFor(RedeemScript) + SizeOfRedeemScript. For a 2-of-3 multsig input, you will thus have 1 + 2*(1 + 72) + 2 + 105 = 254 as the size in bytes of your witness.

The formula for calculating block weight is base size * 3 + total size. The base size is the size of all non-witness data, so your base size is 76 bytes. The total size is the size of all data, including witnesses, so your total size will be 76 + 254 = 330. Plugging this into the formula gets 76 * 3 + 330 = 558. Thus the weight of the P2SH-P2WSH 2-of-3 multisig is 558.

*Note that SizeOfVarIntFor(RedeemScript) is actually two bytes because you need to use OP_PUSHDATA1 since the length of the redeemscript is longer than 75 bytes.

2
  • If SizeOfVarIntFor(RedeemScript) would be be two bytes because redeemscript is longer than 75 bytes, wouldn't the same apply to SizeOfVarIntFor(SizeOfScriptSig) since SizeOfScriptSig is 251?
    – Murch
    Aug 8, 2017 at 22:42
  • 1
    @Murch No. There are two ways of representing the size of things in transactions. Within a script itself, we actually use pushdata opcodes. We need two bytes for scripts longer than 75 bytes because we then need to use the OP_PUSHDATA1 opcode before the size byte. However for sizes of things outside of scripts like SizeOfScriptSig, we use Compact Size Unsigned Integers. The csuint only needs an additional byte on top of the number itself when the number itself needs more than 1 byte. You can see how csuint works here: bitcoin.org/en/…
    – Ava Chow
    Aug 8, 2017 at 22:58
1

The differences between P2SH, P2SH-P2WSH and P2WSH are the following:

  • P2SH: the scriptPubKey has a P2SH program. The scriptSig provides the corresponding script arguments and redeemscript to satisfy the P2SH program.
  • P2SH-P2WSH: the scriptPubKey has a P2SH program. The scriptSig has the witness program and forwards to the witness stack for evaluation. The witness stack provides the script arguments and witness script.
  • P2WSH: the scriptPubKey has a witness program, the scriptSig is empty and the witness stack provides the script arguments and witness script.
  • The witness stack is identical for equivalent P2SH-P2WSH and P2WSH inputs.

So to calculate the size of a P2SH-P2WSH multisig, the script arguments and redeemscript get moved to the witness stack as script arguments and witness script, and you need to add the cost of the forwarding script.

The scriptSig in P2SH-P2WSH is composed of scriptLength witnessProgramLength witnessVersion hashLength hash or varInt PUSHBYTES OP_0 PUSHBYTES <hash>. The length of the scriptSig can be expressed in a 1-byte varInt, so the scriptSig in total takes 1 + 1 + 1 + 1 + 32 = 36 B. This means that the non-witness bytes of the input are the outpoint (32+4 B), the scriptSig (36 B), and the nSequence (4 B) which sum to 76 B in total.

The witness stack has the count of the witness items (1 WU), the three script arguments, an empty dummy element because OP_CHECKMULTISIG pops an additional element of the stack and the two signatures (1+2×(1+72) = 147 WU), and the witness script, witnessScriptLength OP_m n×(PUSHBYTES+pubkey) OP_n OP_CHECKMULTISIG (1+1+3×(1+33)+1+1 = 106 WU).

Altogether, the vsize of a 2-of-3 P2SH-P2WSH input is therefore:

txid:vout:scriptSig:nSeq::witLength:scriptArgs:witScript
 32 +  4 +    36   +  4  +    1    +    147   +    106  = 76 + 254/4 = 139.5 vB 

Full details of all three types follow below for your convenience.

P2SH

The size of a P2SH-based 2-of-3 multisig input works out to be 293, 296 or 297 bytes as described in the question.

PREVOUT:
  hash (32 bytes)
  index (4 bytes)
SCRIPTSIG:
  length (varInt 1 or 3 bytes)
  signatures¹ (1+2×(1+72²) bytes = 147 bytes)
    dummy-OP_0 
    m×(PUSHBYTES+sig)
  OP_PUSHDATA1 len(redeemscript) (2 bytes)
  redeemscript (1+3×(1+33)+1+1 = 105 bytes)
    OP_m n×(PUSHBYTES+pubkey) OP_n OP_CHECKMULTISIG
nSequence (4 bytes)

32 + 4 + 3 + 1 + 2×(1+72) + 2 + 1 + 3×(1+33) + 1 + 1 + 4 =
36 + 3 + 147 + 2 + 105 + 4 = 297 B

Since signatures can be 71 or 72 bytes, it works out that the input needs a 1-byte varInt to express the scriptSig's length for two low-r signatures. If either or both signatures are high-r it needs a 3-byte varInt to express the scriptSig's length.

P2SH-P2WSH

The weight of a P2SH-P2WSH 2-of-3 works out to be 556–558 WU, which translate to 139.0–139.5 vB.

PREVOUT:
  hash (32 bytes)
  index (4 bytes)
SCRIPTSIG:
  length (varInt 1 byte)
  witness program: (1 + 1 + 1 + 32 = 35 bytes)
    length
    version (OP_0) 
    PUSHBYTES <32-byte hash>
nSequence (4 bytes)
WITNESS STACK:
  item count (1 WU)
  script arguments (1 + 2×(1+72²) WU)
    dummy-empty-element¹
    m×(varInt+sig)
  witnessScript (1+1+3×(1+33)+1+1 = 106 WU)
    length (varInt 1 WU)
    OP_m n×(PUSHBYTES+pubkey) OP_n OP_CHECKMULTISIG
  
32 + 4 + 1 + 1 + 1 + 1 + 32 + 4
+ [1 + 1 + 2×(1+72) + 1+1+3×(1+33)+1+1]/4
= 36 + 1 + 35 + 4 + [1 + 147 + 106]/4
= 76 + [254]/4
= 76 + 63.5
= 139.5 vB

P2WSH

The P2WSH has the same witness stack as the P2SH-P2WSH, so it saves exactly the 35 B from circumventing the redeemscript. The weight of a P2WSH 2-of-3 works out to be 416-418 WU which translate to 104.0–104.5 vB.

PREVOUT:
  hash (32 bytes)
  index (4 bytes)
SCRIPTSIG:
  length (varInt 1 byte)
nSequence (4 bytes)
WITNESS STACK:
  item count (1 WU)
  script arguments (1 + 2×(1+72²) WU)
    dummy-empty-element¹ 
    m×(varInt+sig)
  witnessScript (1+1+3×(1+33)+1+1 = 106 WU)
    length (varInt 1 WU)
    OP_m n×(PUSHBYTES+pubkey) OP_n OP_CHECKMULTISIG

32 + 4 + 1 + 4
+ [1 + 1 + 2×(1+72) + 1 + 1 + 3×(1+33) + 1 + 1]/4
= 36 + 1 + 4 + [1 + 147 + 106]/4
= 41 + [254]/4
= 41 + 63.5 
= 104.5 vB

¹ OP_CHECKMULTISIG pops one extra element off the stack
² Signatures can be 71 or 72 bytes (or seldom even smaller)

0

Your Answer

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

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