• 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

0.0
/channeldb/migration_01_to_11/migration_11_invoices.go
1
package migration_01_to_11
2

3
import (
4
        "bytes"
5
        "encoding/binary"
6
        "fmt"
7
        "io"
8

9
        bitcoinCfg "github.com/btcsuite/btcd/chaincfg"
10
        "github.com/btcsuite/btcd/wire"
11
        lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21"
12
        "github.com/lightningnetwork/lnd/channeldb/migration_01_to_11/zpay32"
13
        "github.com/lightningnetwork/lnd/kvdb"
14
        litecoinCfg "github.com/ltcsuite/ltcd/chaincfg"
15
)
16

17
// MigrateInvoices adds invoice htlcs and a separate cltv delta field to the
18
// invoices.
UNCOV
19
func MigrateInvoices(tx kvdb.RwTx) error {
×
UNCOV
20
        log.Infof("Migrating invoices to new invoice format")
×
UNCOV
21

×
UNCOV
22
        invoiceB := tx.ReadWriteBucket(invoiceBucket)
×
UNCOV
23
        if invoiceB == nil {
×
24
                return nil
×
25
        }
×
26

27
        // Iterate through the entire key space of the top-level invoice bucket.
28
        // If key with a non-nil value stores the next invoice ID which maps to
29
        // the corresponding invoice. Store those keys first, because it isn't
30
        // safe to modify the bucket inside a ForEach loop.
UNCOV
31
        var invoiceKeys [][]byte
×
UNCOV
32
        err := invoiceB.ForEach(func(k, v []byte) error {
×
UNCOV
33
                if v == nil {
×
34
                        return nil
×
35
                }
×
36

UNCOV
37
                invoiceKeys = append(invoiceKeys, k)
×
UNCOV
38

×
UNCOV
39
                return nil
×
40
        })
UNCOV
41
        if err != nil {
×
42
                return err
×
43
        }
×
44

UNCOV
45
        nets := []*bitcoinCfg.Params{
×
UNCOV
46
                &bitcoinCfg.MainNetParams, &bitcoinCfg.SimNetParams,
×
UNCOV
47
                &bitcoinCfg.RegressionNetParams, &bitcoinCfg.TestNet3Params,
×
UNCOV
48
        }
×
UNCOV
49

×
UNCOV
50
        ltcNets := []*litecoinCfg.Params{
×
UNCOV
51
                &litecoinCfg.MainNetParams, &litecoinCfg.SimNetParams,
×
UNCOV
52
                &litecoinCfg.RegressionNetParams, &litecoinCfg.TestNet4Params,
×
UNCOV
53
        }
×
UNCOV
54
        for _, net := range ltcNets {
×
UNCOV
55
                var convertedNet bitcoinCfg.Params
×
UNCOV
56
                convertedNet.Bech32HRPSegwit = net.Bech32HRPSegwit
×
UNCOV
57
                nets = append(nets, &convertedNet)
×
UNCOV
58
        }
×
59

60
        // Iterate over all stored keys and migrate the invoices.
UNCOV
61
        for _, k := range invoiceKeys {
×
UNCOV
62
                v := invoiceB.Get(k)
×
UNCOV
63

×
UNCOV
64
                // Deserialize the invoice with the deserializing function that
×
UNCOV
65
                // was in use for this version of the database.
×
UNCOV
66
                invoiceReader := bytes.NewReader(v)
×
UNCOV
67
                invoice, err := deserializeInvoiceLegacy(invoiceReader)
×
UNCOV
68
                if err != nil {
×
69
                        return err
×
70
                }
×
71

UNCOV
72
                if invoice.Terms.State == ContractAccepted {
×
UNCOV
73
                        return fmt.Errorf("cannot upgrade with invoice(s) " +
×
UNCOV
74
                                "in accepted state, see release notes")
×
UNCOV
75
                }
×
76

77
                // Try to decode the payment request for every possible net to
78
                // avoid passing a the active network to channeldb. This would
79
                // be a layering violation, while this migration is only running
80
                // once and will likely be removed in the future.
UNCOV
81
                var payReq *zpay32.Invoice
×
UNCOV
82
                for _, net := range nets {
×
UNCOV
83
                        payReq, err = zpay32.Decode(
×
UNCOV
84
                                string(invoice.PaymentRequest), net,
×
UNCOV
85
                        )
×
UNCOV
86
                        if err == nil {
×
UNCOV
87
                                break
×
88
                        }
89
                }
UNCOV
90
                if payReq == nil {
×
91
                        return fmt.Errorf("cannot decode payreq")
×
92
                }
×
UNCOV
93
                invoice.FinalCltvDelta = int32(payReq.MinFinalCLTVExpiry())
×
UNCOV
94
                invoice.Expiry = payReq.Expiry()
×
UNCOV
95

×
UNCOV
96
                // Serialize the invoice in the new format and use it to replace
×
UNCOV
97
                // the old invoice in the database.
×
UNCOV
98
                var buf bytes.Buffer
×
UNCOV
99
                if err := serializeInvoice(&buf, &invoice); err != nil {
×
100
                        return err
×
101
                }
×
102

UNCOV
103
                err = invoiceB.Put(k, buf.Bytes())
×
UNCOV
104
                if err != nil {
×
105
                        return err
×
106
                }
×
107
        }
108

UNCOV
109
        log.Infof("Migration of invoices completed!")
×
UNCOV
110
        return nil
×
111
}
112

UNCOV
113
func deserializeInvoiceLegacy(r io.Reader) (Invoice, error) {
×
UNCOV
114
        var err error
×
UNCOV
115
        invoice := Invoice{}
×
UNCOV
116

×
UNCOV
117
        // TODO(roasbeef): use read full everywhere
×
UNCOV
118
        invoice.Memo, err = wire.ReadVarBytes(r, 0, MaxMemoSize, "")
×
UNCOV
119
        if err != nil {
×
120
                return invoice, err
×
121
        }
×
UNCOV
122
        invoice.Receipt, err = wire.ReadVarBytes(r, 0, MaxReceiptSize, "")
×
UNCOV
123
        if err != nil {
×
124
                return invoice, err
×
125
        }
×
126

UNCOV
127
        invoice.PaymentRequest, err = wire.ReadVarBytes(r, 0, MaxPaymentRequestSize, "")
×
UNCOV
128
        if err != nil {
×
129
                return invoice, err
×
130
        }
×
131

UNCOV
132
        birthBytes, err := wire.ReadVarBytes(r, 0, 300, "birth")
×
UNCOV
133
        if err != nil {
×
134
                return invoice, err
×
135
        }
×
UNCOV
136
        if err := invoice.CreationDate.UnmarshalBinary(birthBytes); err != nil {
×
137
                return invoice, err
×
138
        }
×
139

UNCOV
140
        settledBytes, err := wire.ReadVarBytes(r, 0, 300, "settled")
×
UNCOV
141
        if err != nil {
×
142
                return invoice, err
×
143
        }
×
UNCOV
144
        if err := invoice.SettleDate.UnmarshalBinary(settledBytes); err != nil {
×
145
                return invoice, err
×
146
        }
×
147

UNCOV
148
        if _, err := io.ReadFull(r, invoice.Terms.PaymentPreimage[:]); err != nil {
×
149
                return invoice, err
×
150
        }
×
UNCOV
151
        var scratch [8]byte
×
UNCOV
152
        if _, err := io.ReadFull(r, scratch[:]); err != nil {
×
153
                return invoice, err
×
154
        }
×
UNCOV
155
        invoice.Terms.Value = lnwire.MilliSatoshi(byteOrder.Uint64(scratch[:]))
×
UNCOV
156

×
UNCOV
157
        if err := binary.Read(r, byteOrder, &invoice.Terms.State); err != nil {
×
158
                return invoice, err
×
159
        }
×
160

UNCOV
161
        if err := binary.Read(r, byteOrder, &invoice.AddIndex); err != nil {
×
162
                return invoice, err
×
163
        }
×
UNCOV
164
        if err := binary.Read(r, byteOrder, &invoice.SettleIndex); err != nil {
×
165
                return invoice, err
×
166
        }
×
UNCOV
167
        if err := binary.Read(r, byteOrder, &invoice.AmtPaid); err != nil {
×
168
                return invoice, err
×
169
        }
×
170

UNCOV
171
        return invoice, nil
×
172
}
173

174
// serializeInvoiceLegacy serializes an invoice in the format of the previous db
175
// version.
UNCOV
176
func serializeInvoiceLegacy(w io.Writer, i *Invoice) error {
×
UNCOV
177
        if err := wire.WriteVarBytes(w, 0, i.Memo[:]); err != nil {
×
178
                return err
×
179
        }
×
UNCOV
180
        if err := wire.WriteVarBytes(w, 0, i.Receipt[:]); err != nil {
×
181
                return err
×
182
        }
×
UNCOV
183
        if err := wire.WriteVarBytes(w, 0, i.PaymentRequest[:]); err != nil {
×
184
                return err
×
185
        }
×
186

UNCOV
187
        birthBytes, err := i.CreationDate.MarshalBinary()
×
UNCOV
188
        if err != nil {
×
189
                return err
×
190
        }
×
191

UNCOV
192
        if err := wire.WriteVarBytes(w, 0, birthBytes); err != nil {
×
193
                return err
×
194
        }
×
195

UNCOV
196
        settleBytes, err := i.SettleDate.MarshalBinary()
×
UNCOV
197
        if err != nil {
×
198
                return err
×
199
        }
×
200

UNCOV
201
        if err := wire.WriteVarBytes(w, 0, settleBytes); err != nil {
×
202
                return err
×
203
        }
×
204

UNCOV
205
        if _, err := w.Write(i.Terms.PaymentPreimage[:]); err != nil {
×
206
                return err
×
207
        }
×
208

UNCOV
209
        var scratch [8]byte
×
UNCOV
210
        byteOrder.PutUint64(scratch[:], uint64(i.Terms.Value))
×
UNCOV
211
        if _, err := w.Write(scratch[:]); err != nil {
×
212
                return err
×
213
        }
×
214

UNCOV
215
        if err := binary.Write(w, byteOrder, i.Terms.State); err != nil {
×
216
                return err
×
217
        }
×
218

UNCOV
219
        if err := binary.Write(w, byteOrder, i.AddIndex); err != nil {
×
220
                return err
×
221
        }
×
UNCOV
222
        if err := binary.Write(w, byteOrder, i.SettleIndex); err != nil {
×
223
                return err
×
224
        }
×
UNCOV
225
        if err := binary.Write(w, byteOrder, int64(i.AmtPaid)); err != nil {
×
226
                return err
×
227
        }
×
228

UNCOV
229
        return nil
×
230
}
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