forked from decred/dcrwallet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
size.go
127 lines (111 loc) · 3.89 KB
/
size.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright (c) 2016 The btcsuite developers
// Copyright (c) 2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package txsizes
import (
"github.com/decred/dcrd/wire"
h "github.com/decred/dcrwallet/internal/helpers"
)
// ScriptSizer signature script sizing interface
type ScriptSizer interface {
ScriptSize() int
}
type sigScriptSize int
func (s sigScriptSize) ScriptSize() int { return int(s) }
// TODO: add multi sig sizer type
// Worst case script and input/output size estimates.
const (
// RedeemP2PKHSigScriptSize is the worst case (largest) serialize size
// of a transaction input script that redeems a compressed P2PKH output.
// It is calculated as:
//
// - OP_DATA_73
// - 72 bytes DER signature + 1 byte sighash
// - OP_DATA_33
// - 33 bytes serialized compressed pubkey
RedeemP2PKHSigScriptSize = 1 + 73 + 1 + 33
// RedeemP2SHSigScriptSize is the worst case (largest) serialize size
// of a transaction input script that redeems a P2SH output.
// It is calculated as:
//
// - OP_DATA_73
// - 73-byte signature
// - OP_DATA_35
// - OP_DATA_33
// - 33 bytes serialized compressed pubkey
// - OP_CHECKSIG
RedeemP2SHSigScriptSize = 1 + 73 + 1 + 1 + 33 + 1
// RedeemP2PKHInputSize is the worst case (largest) serialize size of a
// transaction input redeeming a compressed P2PKH output. It is
// calculated as:
//
// - 32 bytes previous tx
// - 4 bytes output index
// - 1 byte tree
// - 8 bytes amount
// - 4 bytes block height
// - 4 bytes block index
// - 1 byte compact int encoding value 107
// - 107 bytes signature script
// - 4 bytes sequence
RedeemP2PKHInputSize = 32 + 4 + 1 + 8 + 4 + 4 + 1 + RedeemP2PKHSigScriptSize + 4
// P2PKHPkScriptSize is the size of a transaction output script that
// pays to a compressed pubkey hash. It is calculated as:
//
// - OP_DUP
// - OP_HASH160
// - OP_DATA_20
// - 20 bytes pubkey hash
// - OP_EQUALVERIFY
// - OP_CHECKSIG
P2PKHPkScriptSize = 1 + 1 + 1 + 20 + 1 + 1
// P2PKHOutputSize is the serialize size of a transaction output with a
// P2PKH output script. It is calculated as:
//
// - 8 bytes output value
// - 2 bytes version
// - 1 byte compact int encoding value 25
// - 25 bytes P2PKH output script
P2PKHOutputSize = 8 + 2 + 1 + 25
// signature script definitions
P2SHScriptSize = sigScriptSize(RedeemP2SHSigScriptSize)
P2PKHScriptSize = sigScriptSize(RedeemP2PKHSigScriptSize)
)
// EstimateSerializeSize returns a worst case serialize size estimate for a
// signed transaction that spends a number of outputs and contains each
// transaction output from txOuts. The estimated size is incremented for an
// additional P2PKH change output if addChangeOutput is true.
func EstimateSerializeSize(scriptSizers []ScriptSizer, txOuts []*wire.TxOut, addChangeOutput bool) int {
// generate the estimated sizes of the inputs
txInsSize := 0
for _, sizer := range scriptSizers {
txInsSize += EstimateInputSize(sizer.ScriptSize())
}
inputCount := len(scriptSizers)
outputCount := len(txOuts)
changeSize := 0
if addChangeOutput {
changeSize = P2PKHOutputSize
outputCount++
}
// 12 additional bytes are for version, locktime and expiry.
return 12 + (2 * wire.VarIntSerializeSize(uint64(inputCount))) +
wire.VarIntSerializeSize(uint64(outputCount)) +
txInsSize +
h.SumOutputSerializeSizes(txOuts) +
changeSize
}
// EstimateInputSize returns the worst case serialize size estimate for a tx input
// - 32 bytes previous tx
// - 4 bytes output index
// - 1 byte tree
// - 8 bytes amount
// - 4 bytes block height
// - 4 bytes block index
// - the compact int representation of the script size
// - the supplied script size
// - 4 bytes sequence
func EstimateInputSize(scriptSize int) int {
return 32 + 4 + 1 + 8 + 4 + 4 + wire.VarIntSerializeSize(uint64(scriptSize)) + scriptSize + 4
}