@@ -22,6 +22,7 @@ import (
22
22
"github.com/btcsuite/btcwallet/walletdb"
23
23
"github.com/lightningnetwork/lnd/aliasmgr"
24
24
"github.com/lightningnetwork/lnd/batch"
25
+ "github.com/lightningnetwork/lnd/fn/v2"
25
26
"github.com/lightningnetwork/lnd/graph/db/models"
26
27
"github.com/lightningnetwork/lnd/input"
27
28
"github.com/lightningnetwork/lnd/kvdb"
@@ -284,6 +285,13 @@ func (c *KVStore) getChannelMap(edges kvdb.RBucket) (
284
285
case errors .Is (err , ErrEdgePolicyOptionalFieldNotFound ):
285
286
return nil
286
287
288
+ // We don't want a single policy with bad TLV data to stop us
289
+ // from loading the rest of the data, so we just skip this
290
+ // policy. This is for backwards compatibility since we did not
291
+ // use to validate TLV data in the past before persisting it.
292
+ case errors .Is (err , ErrParsingExtraTLVBytes ):
293
+ return nil
294
+
287
295
case err != nil :
288
296
return err
289
297
}
@@ -2342,7 +2350,7 @@ func (c *KVStore) FilterChannelRange(startHeight,
2342
2350
edge , err := deserializeChanEdgePolicyRaw (r )
2343
2351
if err != nil && ! errors .Is (
2344
2352
err , ErrEdgePolicyOptionalFieldNotFound ,
2345
- ) {
2353
+ ) && ! errors . Is ( err , ErrParsingExtraTLVBytes ) {
2346
2354
2347
2355
return err
2348
2356
}
@@ -2357,7 +2365,7 @@ func (c *KVStore) FilterChannelRange(startHeight,
2357
2365
edge , err := deserializeChanEdgePolicyRaw (r )
2358
2366
if err != nil && ! errors .Is (
2359
2367
err , ErrEdgePolicyOptionalFieldNotFound ,
2360
- ) {
2368
+ ) && ! errors . Is ( err , ErrParsingExtraTLVBytes ) {
2361
2369
2362
2370
return err
2363
2371
}
@@ -4334,15 +4342,20 @@ func putChanEdgePolicy(edges kvdb.RwBucket, edge *models.ChannelEdgePolicy,
4334
4342
// need to deserialize the existing policy within the database
4335
4343
// (now outdated by the new one), and delete its corresponding
4336
4344
// entry within the update index. We'll ignore any
4337
- // ErrEdgePolicyOptionalFieldNotFound error, as we only need
4338
- // the channel ID and update time to delete the entry.
4345
+ // ErrEdgePolicyOptionalFieldNotFound or ErrParsingExtraTLVBytes
4346
+ // errors, as we only need the channel ID and update time to
4347
+ // delete the entry.
4348
+ //
4339
4349
// TODO(halseth): get rid of these invalid policies in a
4340
4350
// migration.
4351
+ // TODO(elle): complete the above TODO in migration from kvdb
4352
+ // to SQL.
4341
4353
oldEdgePolicy , err := deserializeChanEdgePolicy (
4342
4354
bytes .NewReader (edgeBytes ),
4343
4355
)
4344
4356
if err != nil &&
4345
- ! errors .Is (err , ErrEdgePolicyOptionalFieldNotFound ) {
4357
+ ! errors .Is (err , ErrEdgePolicyOptionalFieldNotFound ) &&
4358
+ ! errors .Is (err , ErrParsingExtraTLVBytes ) {
4346
4359
4347
4360
return err
4348
4361
}
@@ -4449,6 +4462,11 @@ func fetchChanEdgePolicy(edges kvdb.RBucket, chanID []byte,
4449
4462
case errors .Is (err , ErrEdgePolicyOptionalFieldNotFound ):
4450
4463
return nil , nil
4451
4464
4465
+ // If the policy contains invalid TLV bytes, we return nil as if
4466
+ // the policy was unknown.
4467
+ case errors .Is (err , ErrParsingExtraTLVBytes ):
4468
+ return nil , nil
4469
+
4452
4470
case err != nil :
4453
4471
return nil , err
4454
4472
}
@@ -4568,15 +4586,18 @@ func serializeChanEdgePolicy(w io.Writer, edge *models.ChannelEdgePolicy,
4568
4586
4569
4587
func deserializeChanEdgePolicy (r io.Reader ) (* models.ChannelEdgePolicy , error ) {
4570
4588
// Deserialize the policy. Note that in case an optional field is not
4571
- // found, both an error and a populated policy object are returned.
4572
- edge , deserializeErr := deserializeChanEdgePolicyRaw (r )
4573
- if deserializeErr != nil &&
4574
- ! errors .Is (deserializeErr , ErrEdgePolicyOptionalFieldNotFound ) {
4589
+ // found or if the edge has invalid TLV data, then both an error and a
4590
+ // populated policy object are returned so that the caller can decide
4591
+ // if it still wants to use the edge or not.
4592
+ edge , err := deserializeChanEdgePolicyRaw (r )
4593
+ if err != nil &&
4594
+ ! errors .Is (err , ErrEdgePolicyOptionalFieldNotFound ) &&
4595
+ ! errors .Is (err , ErrParsingExtraTLVBytes ) {
4575
4596
4576
- return nil , deserializeErr
4597
+ return nil , err
4577
4598
}
4578
4599
4579
- return edge , deserializeErr
4600
+ return edge , err
4580
4601
}
4581
4602
4582
4603
func deserializeChanEdgePolicyRaw (r io.Reader ) (* models.ChannelEdgePolicy ,
@@ -4663,6 +4684,22 @@ func deserializeChanEdgePolicyRaw(r io.Reader) (*models.ChannelEdgePolicy,
4663
4684
edge .ExtraOpaqueData = opq [8 :]
4664
4685
}
4665
4686
4687
+ // Attempt to extract the inbound fee from the opaque data. If we fail
4688
+ // to parse the TLV here, we return an error we also return the edge
4689
+ // so that the caller can still use it. This is for backwards
4690
+ // compatibility in case we have already persisted some policies that
4691
+ // have invalid TLV data.
4692
+ var inboundFee lnwire.Fee
4693
+ typeMap , err := edge .ExtraOpaqueData .ExtractRecords (& inboundFee )
4694
+ if err != nil {
4695
+ return edge , fmt .Errorf ("%w: %w" , ErrParsingExtraTLVBytes , err )
4696
+ }
4697
+
4698
+ val , ok := typeMap [lnwire .FeeRecordType ]
4699
+ if ok && val == nil {
4700
+ edge .InboundFee = fn .Some (inboundFee )
4701
+ }
4702
+
4666
4703
return edge , nil
4667
4704
}
4668
4705
0 commit comments