Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/release-notes/release-notes-0.21.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@
transitions during startup, avoiding lost unlocks during slow database
initialization.

* [Required `total_amount_msat` for blinded final
hops](https://github.com/lightningnetwork/lnd/pull/10597). Per BOLT 4, when
`encrypted_recipient_data` is present on a final node, `total_amount_msat`
must be included. Validation is now performed explicitly at payload parsing
time.

# New Features

- Basic Support for [onion messaging forwarding](https://github.com/lightningnetwork/lnd/pull/9868)
Expand Down
10 changes: 10 additions & 0 deletions htlcswitch/hop/payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ func ValidateParsedPayloadTypes(parsedTypes tlv.TypeMap,
_, hasAMP := parsedTypes[record.AMPOnionType]
_, hasEncryptedData := parsedTypes[record.EncryptedDataOnionType]
_, hasBlinding := parsedTypes[record.BlindingPointOnionType]
_, hasTotalAmtMsatBlinded := parsedTypes[record.TotalAmtMsatBlindedType]

// All cleartext hops (including final hop) and the final hop in a
// blinded path require the forwading amount and expiry TLVs to be set.
Expand Down Expand Up @@ -311,6 +312,15 @@ func ValidateParsedPayloadTypes(parsedTypes tlv.TypeMap,
FinalHop: isFinalHop,
}

// If encrypted data is present and is final hop, we require that
// total_amount_msat is set.
case isFinalHop && hasEncryptedData && !hasTotalAmtMsatBlinded:
return ErrInvalidPayload{
Type: record.TotalAmtMsatBlindedType,
Violation: OmittedViolation,
FinalHop: isFinalHop,
}

// Hops that need forwarding info must include an amount to forward.
case needFwdInfo && !hasAmt:
return ErrInvalidPayload{
Expand Down
25 changes: 25 additions & 0 deletions htlcswitch/hop/payload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,8 @@ var decodePayloadTests = []decodePayloadTest{
0x04, 0x00,
// encrypted data
0x0a, 0x03, 0x03, 0x02, 0x01,
// total_amount
0x12, 0x00,
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the zero-length value here (0x12, 0x00) — type 18, length 0 — decodes as 0 for a tuint64, but is enough to mark the field as present in the parsed type map, which is all this layer checks. Worth a short comment to make that intent clear.

shouldHaveEncData: true,
},
Expand All @@ -389,6 +391,8 @@ var decodePayloadTests = []decodePayloadTest{
0x04, 0x00,
// encrypted data
0x0a, 0x03, 0x03, 0x02, 0x01,
// total_amount
0x12, 0x00,
},
shouldHaveEncData: true,
expErr: hop.ErrInvalidPayload{
Expand All @@ -397,6 +401,25 @@ var decodePayloadTests = []decodePayloadTest{
FinalHop: true,
},
},
{
name: "final blinded missing total_amount",
isFinalHop: true,
updateAddBlinded: true,
payload: []byte{
// amount
0x02, 0x00,
// cltv
0x04, 0x00,
// encrypted data
0x0a, 0x03, 0x03, 0x02, 0x01,
},
shouldHaveEncData: true,
expErr: hop.ErrInvalidPayload{
Type: record.TotalAmtMsatBlindedType,
Violation: hop.OmittedViolation,
FinalHop: true,
},
},
{
name: "final blinded missing cltv",
isFinalHop: true,
Expand All @@ -406,6 +429,8 @@ var decodePayloadTests = []decodePayloadTest{
0x02, 0x00,
// encrypted data
0x0a, 0x03, 0x03, 0x02, 0x01,
// total_amount
0x12, 0x00,
},
shouldHaveEncData: true,
expErr: hop.ErrInvalidPayload{
Expand Down
Loading