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

lightningnetwork / lnd / 14193549836

01 Apr 2025 10:40AM UTC coverage: 69.046% (+0.007%) from 69.039%
14193549836

Pull #9665

github

web-flow
Merge e8825f209 into b01f4e514
Pull Request #9665: kvdb: bump etcd libs to v3.5.12

133439 of 193262 relevant lines covered (69.05%)

22119.45 hits per line

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

60.95
/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.
19
func MigrateInvoices(tx kvdb.RwTx) error {
2✔
20
        log.Infof("Migrating invoices to new invoice format")
2✔
21

2✔
22
        invoiceB := tx.ReadWriteBucket(invoiceBucket)
2✔
23
        if invoiceB == nil {
2✔
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.
31
        var invoiceKeys [][]byte
2✔
32
        err := invoiceB.ForEach(func(k, v []byte) error {
5✔
33
                if v == nil {
3✔
34
                        return nil
×
35
                }
×
36

37
                invoiceKeys = append(invoiceKeys, k)
3✔
38

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

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

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

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

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

72
                if invoice.Terms.State == ContractAccepted {
4✔
73
                        return fmt.Errorf("cannot upgrade with invoice(s) " +
1✔
74
                                "in accepted state, see release notes")
1✔
75
                }
1✔
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.
81
                var payReq *zpay32.Invoice
2✔
82
                for _, net := range nets {
8✔
83
                        payReq, err = zpay32.Decode(
6✔
84
                                string(invoice.PaymentRequest), net,
6✔
85
                        )
6✔
86
                        if err == nil {
8✔
87
                                break
2✔
88
                        }
89
                }
90
                if payReq == nil {
2✔
91
                        return fmt.Errorf("cannot decode payreq")
×
92
                }
×
93
                invoice.FinalCltvDelta = int32(payReq.MinFinalCLTVExpiry())
2✔
94
                invoice.Expiry = payReq.Expiry()
2✔
95

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

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

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

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

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

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

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

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

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

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

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

171
        return invoice, nil
13✔
172
}
173

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

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

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

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

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

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

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

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

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

229
        return nil
8✔
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