From 1e6fae37f752be7caf73995f693871e4a3d1bd3f Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Tue, 2 Apr 2024 10:56:08 -0400 Subject: [PATCH] htlcswitch: add blinding point to sphinx iterator for decoding --- .../htlc_incoming_contest_resolver.go | 17 ++---- .../htlc_incoming_contest_resolver_test.go | 3 +- contractcourt/interfaces.go | 3 +- htlcswitch/hop/iterator.go | 57 +++++++++++++++---- 4 files changed, 54 insertions(+), 26 deletions(-) diff --git a/contractcourt/htlc_incoming_contest_resolver.go b/contractcourt/htlc_incoming_contest_resolver.go index d43a50d90..9f08f0a7c 100644 --- a/contractcourt/htlc_incoming_contest_resolver.go +++ b/contractcourt/htlc_incoming_contest_resolver.go @@ -7,7 +7,6 @@ import ( "fmt" "io" - "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/txscript" "github.com/lightningnetwork/lnd/channeldb" @@ -18,7 +17,6 @@ import ( "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/queue" - "github.com/lightningnetwork/lnd/tlv" ) // htlcIncomingContestResolver is a ContractResolver that's able to resolve an @@ -522,18 +520,15 @@ func (h *htlcIncomingContestResolver) Supplement(htlc channeldb.HTLC) { func (h *htlcIncomingContestResolver) decodePayload() (*hop.Payload, []byte, error) { - var blindingPoint *btcec.PublicKey - h.htlc.BlindingPoint.WhenSome( - func(b tlv.RecordT[lnwire.BlindingPointTlvType, - *btcec.PublicKey]) { - - blindingPoint = b.Val - }, - ) + blindingInfo := hop.ReconstructBlindingInfo{ + IncomingAmt: h.htlc.Amt, + IncomingExpiry: h.htlc.RefundTimeout, + BlindingKey: h.htlc.BlindingPoint, + } onionReader := bytes.NewReader(h.htlc.OnionBlob[:]) iterator, err := h.OnionProcessor.ReconstructHopIterator( - onionReader, h.htlc.RHash[:], blindingPoint, + onionReader, h.htlc.RHash[:], blindingInfo, ) if err != nil { return nil, nil, err diff --git a/contractcourt/htlc_incoming_contest_resolver_test.go b/contractcourt/htlc_incoming_contest_resolver_test.go index d789858fb..cc3f9c934 100644 --- a/contractcourt/htlc_incoming_contest_resolver_test.go +++ b/contractcourt/htlc_incoming_contest_resolver_test.go @@ -6,7 +6,6 @@ import ( "io/ioutil" "testing" - "github.com/btcsuite/btcd/btcec/v2" sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" @@ -290,7 +289,7 @@ type mockOnionProcessor struct { } func (o *mockOnionProcessor) ReconstructHopIterator(r io.Reader, rHash []byte, - blindingPoint *btcec.PublicKey) (hop.Iterator, error) { + _ hop.ReconstructBlindingInfo) (hop.Iterator, error) { data, err := ioutil.ReadAll(r) if err != nil { diff --git a/contractcourt/interfaces.go b/contractcourt/interfaces.go index 146670a41..a48d2373e 100644 --- a/contractcourt/interfaces.go +++ b/contractcourt/interfaces.go @@ -4,7 +4,6 @@ import ( "context" "io" - "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb/models" @@ -42,7 +41,7 @@ type OnionProcessor interface { // ReconstructHopIterator attempts to decode a valid sphinx packet from // the passed io.Reader instance. ReconstructHopIterator(r io.Reader, rHash []byte, - blindingKey *btcec.PublicKey) (hop.Iterator, error) + blindingInfo hop.ReconstructBlindingInfo) (hop.Iterator, error) } // UtxoSweeper defines the sweep functions that contract court requires. diff --git a/htlcswitch/hop/iterator.go b/htlcswitch/hop/iterator.go index 68b08fe42..35fe5e44e 100644 --- a/htlcswitch/hop/iterator.go +++ b/htlcswitch/hop/iterator.go @@ -55,16 +55,24 @@ type sphinxHopIterator struct { // includes the information required to properly forward the packet to // the next hop. processedPacket *sphinx.ProcessedPacket + + // blindingKit contains the elements required to process hops that are + // part of a blinded route. + blindingKit BlindingKit } // makeSphinxHopIterator converts a processed packet returned from a sphinx -// router and converts it into an hop iterator for usage in the link. +// router and converts it into an hop iterator for usage in the link. A +// blinding kit is passed through for the link to obtain forwarding information +// for blinded routes. func makeSphinxHopIterator(ogPacket *sphinx.OnionPacket, - packet *sphinx.ProcessedPacket) *sphinxHopIterator { + packet *sphinx.ProcessedPacket, + blindingKit BlindingKit) *sphinxHopIterator { return &sphinxHopIterator{ ogPacket: ogPacket, processedPacket: packet, + blindingKit: blindingKit, } } @@ -370,11 +378,24 @@ func (p *OnionProcessor) Stop() error { return nil } -// ReconstructHopIterator attempts to decode a valid sphinx packet from the passed io.Reader -// instance using the rHash as the associated data when checking the relevant -// MACs during the decoding process. +// ReconstructBlindingInfo contains the information required to reconstruct a +// blinded onion. +type ReconstructBlindingInfo struct { + // BlindingKey is the blinding point set in UpdateAddHTLC. + BlindingKey lnwire.BlindingPointRecord + + // IncomingAmt is the amount for the incoming HTLC. + IncomingAmt lnwire.MilliSatoshi + + // IncomingExpiry is the expiry height of the incoming HTLC. + IncomingExpiry uint32 +} + +// ReconstructHopIterator attempts to decode a valid sphinx packet from the +// passed io.Reader instance using the rHash as the associated data when +// checking the relevant MACs during the decoding process. func (p *OnionProcessor) ReconstructHopIterator(r io.Reader, rHash []byte, - blindingPoint *btcec.PublicKey) (Iterator, error) { + blindingInfo ReconstructBlindingInfo) (Iterator, error) { onionPkt := &sphinx.OnionPacket{} if err := onionPkt.Decode(r); err != nil { @@ -382,9 +403,11 @@ func (p *OnionProcessor) ReconstructHopIterator(r io.Reader, rHash []byte, } var opts []sphinx.ProcessOnionOpt - if blindingPoint != nil { - opts = append(opts, sphinx.WithBlindingPoint(blindingPoint)) - } + blindingInfo.BlindingKey.WhenSome(func( + r tlv.RecordT[lnwire.BlindingPointTlvType, *btcec.PublicKey]) { + + opts = append(opts, sphinx.WithBlindingPoint(r.Val)) + }) // Attempt to process the Sphinx packet. We include the payment hash of // the HTLC as it's authenticated within the Sphinx packet itself as @@ -398,7 +421,12 @@ func (p *OnionProcessor) ReconstructHopIterator(r io.Reader, rHash []byte, return nil, err } - return makeSphinxHopIterator(onionPkt, sphinxPacket), nil + return makeSphinxHopIterator(onionPkt, sphinxPacket, BlindingKit{ + Processor: p.router, + UpdateAddBlinding: blindingInfo.BlindingKey, + IncomingAmount: blindingInfo.IncomingAmt, + IncomingCltv: blindingInfo.IncomingExpiry, + }), nil } // DecodeHopIteratorRequest encapsulates all date necessary to process an onion @@ -575,7 +603,14 @@ func (p *OnionProcessor) DecodeHopIterators(id []byte, // Finally, construct a hop iterator from our processed sphinx // packet, simultaneously caching the original onion packet. - resp.HopIterator = makeSphinxHopIterator(&onionPkts[i], &packets[i]) + resp.HopIterator = makeSphinxHopIterator( + &onionPkts[i], &packets[i], BlindingKit{ + Processor: p.router, + UpdateAddBlinding: reqs[i].BlindingPoint, + IncomingAmount: reqs[i].IncomingAmount, + IncomingCltv: reqs[i].IncomingCltv, + }, + ) } return resps, nil