size.go raw

   1  // Package txsizes Copyright (c) 2016 The btcsuite developers
   2  package txsizes
   3  
   4  import (
   5  	"github.com/p9c/p9/pkg/blockchain"
   6  	h "github.com/p9c/p9/pkg/util/helpers"
   7  	"github.com/p9c/p9/pkg/wire"
   8  )
   9  
  10  // Worst case script and input/output size estimates.
  11  const (
  12  	// RedeemP2PKHSigScriptSize is the worst case (largest) serialize size of a transaction input script that redeems a
  13  	// compressed P2PKH output. It is calculated as:
  14  	//
  15  	//   - OP_DATA_73
  16  	//   - 72 bytes DER signature + 1 byte sighash
  17  	//   - OP_DATA_33
  18  	//   - 33 bytes serialized compressed pubkey
  19  	RedeemP2PKHSigScriptSize = 1 + 73 + 1 + 33
  20  	// P2PKHPkScriptSize is the size of a transaction output script that pays to a compressed pubkey hash. It is
  21  	// calculated as:
  22  	//
  23  	//   - OP_DUP
  24  	//   - OP_HASH160
  25  	//   - OP_DATA_20
  26  	//   - 20 bytes pubkey hash
  27  	//   - OP_EQUALVERIFY
  28  	//   - OP_CHECKSIG
  29  	P2PKHPkScriptSize = 1 + 1 + 1 + 20 + 1 + 1
  30  	// RedeemP2PKHInputSize is the worst case (largest) serialize size of a transaction input redeeming a compressed
  31  	// P2PKH output. It is calculated as:
  32  	//
  33  	//   - 32 bytes previous tx
  34  	//   - 4 bytes output index
  35  	//   - 1 byte compact int encoding value 107
  36  	//   - 107 bytes signature script
  37  	//   - 4 bytes sequence
  38  	RedeemP2PKHInputSize = 32 + 4 + 1 + RedeemP2PKHSigScriptSize + 4
  39  	// P2PKHOutputSize is the serialize size of a transaction output with a P2PKH output script. It is calculated as:
  40  	//
  41  	//   - 8 bytes output value
  42  	//   - 1 byte compact int encoding value 25
  43  	//   - 25 bytes P2PKH output script
  44  	P2PKHOutputSize = 8 + 1 + P2PKHPkScriptSize
  45  	// // P2WPKHPkScriptSize is the size of a transaction output script that pays to a
  46  	// // witness pubkey hash. It is calculated as:
  47  	// //
  48  	// //   - OP_0
  49  	// //   - OP_DATA_20
  50  	// //   - 20 bytes pubkey hash
  51  	// P2WPKHPkScriptSize = 1 + 1 + 20
  52  	// // P2WPKHOutputSize is the serialize size of a transaction output with a P2WPKH output script. It is calculated as:
  53  	// //
  54  	// //   - 8 bytes output value
  55  	// //   - 1 byte compact int encoding value 22
  56  	// //   - 22 bytes P2PKH output script
  57  	// P2WPKHOutputSize = 8 + 1 + P2WPKHPkScriptSize
  58  	// // RedeemP2WPKHScriptSize is the size of a transaction input script that spends
  59  	// // a pay-to-witness-public-key hash (P2WPKH). The redeem script for P2WPKH
  60  	// // spends MUST be empty.
  61  	// RedeemP2WPKHScriptSize = 0
  62  	// // RedeemP2WPKHInputSize is the worst case size of a transaction input redeeming a P2WPKH output. It is calculated
  63  	// // as:
  64  	// //
  65  	// //   - 32 bytes previous tx
  66  	// //   - 4 bytes output index
  67  	// //   - 1 byte encoding empty redeem script
  68  	// //   - 0 bytes redeem script
  69  	// //   - 4 bytes sequence
  70  	// RedeemP2WPKHInputSize = 32 + 4 + 1 + RedeemP2WPKHScriptSize + 4
  71  	// // RedeemNestedP2WPKHScriptSize is the worst case size of a transaction input
  72  	// // script that redeems a pay-to-witness-key hash nested in P2SH (P2SH-P2WPKH).
  73  	// // It is calculated as:
  74  	// //
  75  	// //   - 1 byte compact int encoding value 22
  76  	// //   - OP_0
  77  	// //   - 1 byte compact int encoding value 20
  78  	// //   - 20 byte key hash
  79  	// RedeemNestedP2WPKHScriptSize = 1 + 1 + 1 + 20
  80  	// // RedeemNestedP2WPKHInputSize is the worst case size of a transaction input redeeming a P2SH-P2WPKH output. It is
  81  	// // calculated as:
  82  	// //
  83  	// //   - 32 bytes previous tx
  84  	// //   - 4 bytes output index
  85  	// //   - 1 byte compact int encoding value 23
  86  	// //   - 23 bytes redeem script (scriptSig)
  87  	// //   - 4 bytes sequence
  88  	// RedeemNestedP2WPKHInputSize = 32 + 4 + 1 + RedeemNestedP2WPKHScriptSize + 4
  89  	// // RedeemP2WPKHInputWitnessWeight is the worst case weight of a witness for
  90  	// // spending P2WPKH and nested P2WPKH outputs. It is calculated as:
  91  	// //
  92  	// //   - 1 wu compact int encoding value 2 (number of items)
  93  	// //   - 1 wu compact int encoding value 73
  94  	// //   - 72 wu DER signature + 1 wu sighash
  95  	// //   - 1 wu compact int encoding value 33
  96  	// //   - 33 wu serialized compressed pubkey
  97  	// RedeemP2WPKHInputWitnessWeight = 1 + 1 + 73 + 1 + 33
  98  )
  99  
 100  // EstimateSerializeSize returns a worst case serialize size estimate for a signed transaction that spends inputCount
 101  // number of compressed P2PKH outputs and contains each transaction output from txOuts. The estimated size is
 102  // incremented for an additional P2PKH change output if addChangeOutput is true.
 103  func EstimateSerializeSize(inputCount int, txOuts []*wire.TxOut, addChangeOutput bool) int {
 104  	changeSize := 0
 105  	outputCount := len(txOuts)
 106  	if addChangeOutput {
 107  		changeSize = P2PKHOutputSize
 108  		outputCount++
 109  	}
 110  	// 8 additional bytes are for version and locktime
 111  	return 8 + wire.VarIntSerializeSize(uint64(inputCount)) +
 112  		wire.VarIntSerializeSize(uint64(outputCount)) +
 113  		inputCount*RedeemP2PKHInputSize +
 114  		h.SumOutputSerializeSizes(txOuts) +
 115  		changeSize
 116  }
 117  
 118  // EstimateVirtualSize returns a worst case virtual size estimate for a signed transaction that spends the given number
 119  // of P2PKH, P2WPKH and (nested) P2SH-P2WPKH outputs, and contains each transaction output from txOuts. The estimate is
 120  // incremented for an additional P2PKH change output if addChangeOutput is true.
 121  func EstimateVirtualSize(numP2PKHIns, numP2WPKHIns, numNestedP2WPKHIns int,
 122  	txOuts []*wire.TxOut, addChangeOutput bool,
 123  ) int {
 124  	changeSize := 0
 125  	// outputCount := len(txOuts)
 126  	if addChangeOutput {
 127  		// We are always using P2WPKH as change output.
 128  		changeSize = P2PKHOutputSize
 129  		// outputCount++
 130  	}
 131  	// Version 4 bytes + LockTime 4 bytes + Serialized var int size for the number of transaction inputs and outputs +
 132  	// size of redeem scripts + the size out the serialized outputs and change.
 133  	baseSize := 8 +
 134  		wire.VarIntSerializeSize(
 135  			uint64(numP2PKHIns+numP2WPKHIns+numNestedP2WPKHIns),
 136  		) +
 137  		wire.VarIntSerializeSize(uint64(len(txOuts))) +
 138  		numP2PKHIns*RedeemP2PKHInputSize +
 139  		// numP2WPKHIns*RedeemP2PKHInputSize +
 140  		// numNestedP2WPKHIns*RedeemNestedP2WPKHInputSize +
 141  		h.SumOutputSerializeSizes(txOuts) +
 142  		changeSize
 143  	// If this transaction has any witness inputs, we must count the witness data.
 144  	witnessWeight := 0
 145  	// if numP2WPKHIns+numNestedP2WPKHIns > 0 {
 146  	// 	// Additional 2 weight units for segwit marker + flag.
 147  	// 	witnessWeight = 2 +
 148  	// 		wire.VarIntSerializeSize(
 149  	// 			uint64(numP2WPKHIns+numNestedP2WPKHIns)) +
 150  	// 		numP2WPKHIns*RedeemP2WPKHInputWitnessWeight +
 151  	// 		numNestedP2WPKHIns*RedeemP2WPKHInputWitnessWeight
 152  	// }
 153  	// We add 3 to the witness weight to make sure the result is always rounded up.
 154  	return baseSize + (witnessWeight+3)/blockchain.WitnessScaleFactor
 155  }
 156