• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 15561477203

10 Jun 2025 01:54PM UTC coverage: 58.351% (-10.1%) from 68.487%
15561477203

Pull #9356

github

web-flow
Merge 6440b25db into c6d6d4c0b
Pull Request #9356: lnrpc: add incoming/outgoing channel ids filter to forwarding history request

33 of 36 new or added lines in 2 files covered. (91.67%)

28366 existing lines in 455 files now uncovered.

97715 of 167461 relevant lines covered (58.35%)

1.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.16
/sweep/weight_estimator.go
1
package sweep
2

3
import (
4
        "github.com/btcsuite/btcd/btcutil"
5
        "github.com/btcsuite/btcd/chaincfg/chainhash"
6
        "github.com/btcsuite/btcd/wire"
7
        "github.com/lightningnetwork/lnd/input"
8
        "github.com/lightningnetwork/lnd/lntypes"
9
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
10
)
11

12
// weightEstimator wraps a standard weight estimator instance and adds to that
13
// support for child-pays-for-parent.
14
type weightEstimator struct {
15
        estimator     input.TxWeightEstimator
16
        feeRate       chainfee.SatPerKWeight
17
        parents       map[chainhash.Hash]struct{}
18
        parentsFee    btcutil.Amount
19
        parentsWeight lntypes.WeightUnit
20

21
        // maxFeeRate is the max allowed fee rate configured by the user.
22
        maxFeeRate chainfee.SatPerKWeight
23
}
24

25
// newWeightEstimator instantiates a new sweeper weight estimator.
26
func newWeightEstimator(
27
        feeRate, maxFeeRate chainfee.SatPerKWeight) *weightEstimator {
3✔
28

3✔
29
        return &weightEstimator{
3✔
30
                feeRate:    feeRate,
3✔
31
                maxFeeRate: maxFeeRate,
3✔
32
                parents:    make(map[chainhash.Hash]struct{}),
3✔
33
        }
3✔
34
}
3✔
35

36
// add adds the weight of the given input to the weight estimate.
37
func (w *weightEstimator) add(inp input.Input) error {
3✔
38
        // If there is a parent tx, add the parent's fee and weight.
3✔
39
        w.tryAddParent(inp)
3✔
40

3✔
41
        wt := inp.WitnessType()
3✔
42

3✔
43
        return wt.AddWeightEstimation(&w.estimator)
3✔
44
}
3✔
45

46
// tryAddParent examines the input and updates parent tx totals if required for
47
// cpfp.
48
func (w *weightEstimator) tryAddParent(inp input.Input) {
3✔
49
        // Get unconfirmed parent info from the input.
3✔
50
        unconfParent := inp.UnconfParent()
3✔
51

3✔
52
        // If there is no parent, there is nothing to add.
3✔
53
        if unconfParent == nil {
6✔
54
                return
3✔
55
        }
3✔
56

57
        // If we've already accounted for the parent tx, don't do it
58
        // again. This can happens when two outputs of the parent tx are
59
        // included in the same sweep tx.
60
        parentHash := inp.OutPoint().Hash
3✔
61
        if _, ok := w.parents[parentHash]; ok {
3✔
62
                return
×
63
        }
×
64

65
        // Calculate parent fee rate.
66
        parentFeeRate := chainfee.SatPerKWeight(unconfParent.Fee) * 1000 /
3✔
67
                chainfee.SatPerKWeight(unconfParent.Weight)
3✔
68

3✔
69
        // Ignore parents that pay at least the fee rate of this transaction.
3✔
70
        // Parent pays for child is not happening.
3✔
71
        if parentFeeRate >= w.feeRate {
6✔
72
                return
3✔
73
        }
3✔
74

75
        // Include parent.
76
        w.parents[parentHash] = struct{}{}
3✔
77
        w.parentsFee += unconfParent.Fee
3✔
78
        w.parentsWeight += unconfParent.Weight
3✔
79
}
80

81
// addP2WKHOutput updates the weight estimate to account for an additional
82
// native P2WKH output.
83
func (w *weightEstimator) addP2WKHOutput() {
3✔
84
        w.estimator.AddP2WKHOutput()
3✔
85
}
3✔
86

87
// addP2TROutput updates the weight estimate to account for an additional native
88
// SegWit v1 P2TR output.
89
func (w *weightEstimator) addP2TROutput() {
3✔
90
        w.estimator.AddP2TROutput()
3✔
91
}
3✔
92

93
// addP2WSHOutput updates the weight estimate to account for an additional
94
// segwit v0 P2WSH output.
95
func (w *weightEstimator) addP2WSHOutput() {
3✔
96
        w.estimator.AddP2WSHOutput()
3✔
97
}
3✔
98

99
// addOutput updates the weight estimate to account for the known
100
// output given.
101
func (w *weightEstimator) addOutput(txOut *wire.TxOut) {
3✔
102
        w.estimator.AddTxOutput(txOut)
3✔
103
}
3✔
104

105
// weight gets the estimated weight of the transaction.
106
func (w *weightEstimator) weight() lntypes.WeightUnit {
3✔
107
        return w.estimator.Weight()
3✔
108
}
3✔
109

110
// fee returns the tx fee to use for the aggregated inputs and outputs, which
111
// is different from feeWithParent as it doesn't take into account unconfirmed
112
// parent transactions.
113
func (w *weightEstimator) fee() btcutil.Amount {
3✔
114
        // Calculate the weight of the transaction.
3✔
115
        weight := w.estimator.Weight()
3✔
116

3✔
117
        // Calculate the fee.
3✔
118
        fee := w.feeRate.FeeForWeight(weight)
3✔
119

3✔
120
        return fee
3✔
121
}
3✔
122

123
// feeWithParent returns the tx fee to use for the aggregated inputs and
124
// outputs, taking into account unconfirmed parent transactions (cpfp).
125
func (w *weightEstimator) feeWithParent() btcutil.Amount {
3✔
126
        // Calculate fee and weight for just this tx.
3✔
127
        childWeight := w.estimator.Weight()
3✔
128

3✔
129
        // Add combined weight of unconfirmed parent txes.
3✔
130
        totalWeight := childWeight + w.parentsWeight
3✔
131

3✔
132
        // Subtract fee already paid by parents.
3✔
133
        fee := w.feeRate.FeeForWeight(totalWeight) - w.parentsFee
3✔
134

3✔
135
        // Clamp the fee to what would be required if no parent txes were paid
3✔
136
        // for. This is to make sure no rounding errors can get us into trouble.
3✔
137
        childFee := w.feeRate.FeeForWeight(childWeight)
3✔
138
        if childFee > fee {
3✔
139
                fee = childFee
×
140
        }
×
141

142
        // Exit early if maxFeeRate is not set.
143
        if w.maxFeeRate == 0 {
3✔
UNCOV
144
                return fee
×
UNCOV
145
        }
×
146

147
        // Clamp the fee to the max fee rate.
148
        maxFee := w.maxFeeRate.FeeForWeight(childWeight)
3✔
149
        if fee > maxFee {
3✔
UNCOV
150
                // Calculate the effective fee rate for logging.
×
UNCOV
151
                childFeeRate := chainfee.SatPerKWeight(
×
UNCOV
152
                        fee * 1000 / btcutil.Amount(childWeight),
×
UNCOV
153
                )
×
UNCOV
154
                log.Warnf("Child fee rate %v exceeds max allowed fee rate %v, "+
×
UNCOV
155
                        "returning fee %v instead of %v", childFeeRate,
×
UNCOV
156
                        w.maxFeeRate, maxFee, fee)
×
UNCOV
157

×
UNCOV
158
                fee = maxFee
×
UNCOV
159
        }
×
160

161
        return fee
3✔
162
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc