decred.org/dcrwallet/v3@v3.1.0/wallet/txsizes/size.go (about) 1 // Copyright (c) 2016 The btcsuite developers 2 // Copyright (c) 2016-2019 The Decred developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package txsizes 7 8 import "github.com/decred/dcrd/wire" 9 10 // Worst case script and input/output size estimates. 11 const ( 12 // RedeemP2PKSigScriptSize is the worst case (largest) serialize size 13 // of a transaction input script that redeems a compressed P2PK output. 14 // It is calculated as: 15 // 16 // - OP_DATA_73 17 // - 72 bytes DER signature + 1 byte sighash 18 RedeemP2PKSigScriptSize = 1 + 73 19 20 // RedeemP2PKHSigScriptSize is the worst case (largest) serialize size 21 // of a transaction input script that redeems a compressed P2PKH output. 22 // It is calculated as: 23 // 24 // - OP_DATA_73 25 // - 72 bytes DER signature + 1 byte sighash 26 // - OP_DATA_33 27 // - 33 bytes serialized compressed pubkey 28 RedeemP2PKHSigScriptSize = 1 + 73 + 1 + 33 29 30 // RedeemP2SHSigScriptSize is the worst case (largest) serialize size 31 // of a transaction input script that redeems a P2SH output. 32 // It is calculated as: 33 // 34 // - OP_DATA_73 35 // - 73-byte signature 36 // - OP_DATA_35 37 // - OP_DATA_33 38 // - 33 bytes serialized compressed pubkey 39 // - OP_CHECKSIG 40 RedeemP2SHSigScriptSize = 1 + 73 + 1 + 1 + 33 + 1 41 42 // RedeemP2PKHInputSize is the worst case (largest) serialize size of a 43 // transaction input redeeming a compressed P2PKH output. It is 44 // calculated as: 45 // 46 // - 32 bytes previous tx 47 // - 4 bytes output index 48 // - 1 byte tree 49 // - 8 bytes amount 50 // - 4 bytes block height 51 // - 4 bytes block index 52 // - 1 byte compact int encoding value 107 53 // - 107 bytes signature script 54 // - 4 bytes sequence 55 RedeemP2PKHInputSize = 32 + 4 + 1 + 8 + 4 + 4 + 1 + RedeemP2PKHSigScriptSize + 4 56 57 // P2PKHPkScriptSize is the size of a transaction output script that 58 // pays to a compressed pubkey hash. It is calculated as: 59 // 60 // - OP_DUP 61 // - OP_HASH160 62 // - OP_DATA_20 63 // - 20 bytes pubkey hash 64 // - OP_EQUALVERIFY 65 // - OP_CHECKSIG 66 P2PKHPkScriptSize = 1 + 1 + 1 + 20 + 1 + 1 67 68 // P2PKHPkTreasruryScriptSize is the size of a transaction output 69 // script that pays stake change to a compressed pubkey hash. This is 70 // used when a user sends coins to the treasury via OP_TADD. It is 71 // calculated as: 72 // 73 // - OP_SSTXCHANGE 74 // - OP_DUP 75 // - OP_HASH160 76 // - OP_DATA_20 77 // - 20 bytes pubkey hash 78 // - OP_EQUALVERIFY 79 // - OP_CHECKSIG 80 P2PKHPkTreasruryScriptSize = 1 + 1 + 1 + 1 + 20 + 1 + 1 81 82 // P2SHPkScriptSize is the size of a transaction output script that 83 // pays to a script hash. It is calculated as: 84 // 85 // - OP_HASH160 86 // - OP_DATA_20 87 // - 20 bytes script hash 88 // - OP_EQUAL 89 P2SHPkScriptSize = 1 + 1 + 20 + 1 90 91 // TicketCommitmentScriptSize is the size of a ticket purchase commitment 92 // script. It is calculated as: 93 // 94 // - OP_RETURN 95 // - OP_DATA_30 96 // - 20 bytes P2SH/P2PKH 97 // - 8 byte amount 98 // - 2 byte fee range limits 99 TicketCommitmentScriptSize = 1 + 1 + 20 + 8 + 2 100 101 // P2PKHOutputSize is the serialize size of a transaction output with a 102 // P2PKH output script. It is calculated as: 103 // 104 // - 8 bytes output value 105 // - 2 bytes version 106 // - 1 byte compact int encoding value 25 107 // - 25 bytes P2PKH output script 108 P2PKHOutputSize = 8 + 2 + 1 + 25 109 110 // TSPENDInputSize 111 // 112 // - OP_DATA_73 113 // - 73 bytes signature 114 // - OP_DATA_33 115 // - 33 bytes serialized compressed pubkey 116 // - 1 byte OP_TSPEND 117 TSPENDInputSize = 1 + 73 + 1 + 33 + 1 118 ) 119 120 func sumOutputSerializeSizes(outputs []*wire.TxOut) (serializeSize int) { 121 for _, txOut := range outputs { 122 serializeSize += txOut.SerializeSize() 123 } 124 return serializeSize 125 } 126 127 // EstimateSerializeSize returns a worst case serialize size estimate for a 128 // signed transaction that spends a number of outputs and contains each 129 // transaction output from txOuts. The estimated size is incremented for an 130 // additional change output if changeScriptSize is greater than 0. Passing 0 131 // does not add a change output. 132 func EstimateSerializeSize(scriptSizes []int, txOuts []*wire.TxOut, changeScriptSize int) int { 133 // Generate and sum up the estimated sizes of the inputs. 134 txInsSize := 0 135 for _, size := range scriptSizes { 136 txInsSize += EstimateInputSize(size) 137 } 138 139 inputCount := len(scriptSizes) 140 outputCount := len(txOuts) 141 changeSize := 0 142 if changeScriptSize > 0 { 143 changeSize = EstimateOutputSize(changeScriptSize) 144 outputCount++ 145 } 146 147 // 12 additional bytes are for version, locktime and expiry. 148 return 12 + (2 * wire.VarIntSerializeSize(uint64(inputCount))) + 149 wire.VarIntSerializeSize(uint64(outputCount)) + 150 txInsSize + 151 sumOutputSerializeSizes(txOuts) + 152 changeSize 153 } 154 155 // EstimateSerializeSizeFromScriptSizes returns a worst case serialize size 156 // estimate for a signed transaction that spends len(inputSizes) previous 157 // outputs and pays to len(outputSizes) outputs with scripts of the provided 158 // worst-case sizes. The estimated size is incremented for an additional 159 // change output if changeScriptSize is greater than 0. Passing 0 does not 160 // add a change output. 161 func EstimateSerializeSizeFromScriptSizes(inputSizes []int, outputSizes []int, changeScriptSize int) int { 162 // Generate and sum up the estimated sizes of the inputs. 163 txInsSize := 0 164 for _, inputSize := range inputSizes { 165 txInsSize += EstimateInputSize(inputSize) 166 } 167 168 // Generate and sum up the estimated sizes of the outputs. 169 txOutsSize := 0 170 for _, outputSize := range outputSizes { 171 txOutsSize += EstimateOutputSize(outputSize) 172 } 173 174 inputCount := len(inputSizes) 175 outputCount := len(outputSizes) 176 changeSize := 0 177 if changeScriptSize > 0 { 178 changeSize = EstimateOutputSize(changeScriptSize) 179 outputCount++ 180 } 181 182 // 12 additional bytes are for version, locktime and expiry. 183 return 12 + (2 * wire.VarIntSerializeSize(uint64(inputCount))) + 184 wire.VarIntSerializeSize(uint64(outputCount)) + 185 txInsSize + txOutsSize + changeSize 186 } 187 188 // EstimateInputSize returns the worst case serialize size estimate for a tx input 189 // - 32 bytes previous tx 190 // - 4 bytes output index 191 // - 1 byte tree 192 // - 8 bytes amount 193 // - 4 bytes block height 194 // - 4 bytes block index 195 // - the compact int representation of the script size 196 // - the supplied script size 197 // - 4 bytes sequence 198 func EstimateInputSize(scriptSize int) int { 199 return 32 + 4 + 1 + 8 + 4 + 4 + wire.VarIntSerializeSize(uint64(scriptSize)) + scriptSize + 4 200 } 201 202 // EstimateOutputSize returns the worst case serialize size estimate for a tx output 203 // - 8 bytes amount 204 // - 2 bytes version 205 // - the compact int representation of the script size 206 // - the supplied script size 207 func EstimateOutputSize(scriptSize int) int { 208 return 8 + 2 + wire.VarIntSerializeSize(uint64(scriptSize)) + scriptSize 209 }