diff --git a/htlcswitch/circuit_map.go b/htlcswitch/circuit_map.go index 5db36b88..017e2b78 100644 --- a/htlcswitch/circuit_map.go +++ b/htlcswitch/circuit_map.go @@ -9,6 +9,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/lnwire" ) @@ -311,7 +312,7 @@ func (cm *circuitMap) restoreMemState() error { // documented case of stray keystones emerges for // forwarded payments, this check should be removed, but // with extreme caution. - if strayKeystone.OutKey.ChanID != sourceHop { + if strayKeystone.OutKey.ChanID != hop.Source { continue } @@ -396,9 +397,9 @@ func (cm *circuitMap) trimAllOpenCircuits() error { // First, skip any channels that have not been assigned their // final channel identifier, otherwise we would try to trim - // htlcs belonging to the all-zero, sourceHop ID. + // htlcs belonging to the all-zero, hop.Source ID. chanID := activeChannel.ShortChanID() - if chanID == sourceHop { + if chanID == hop.Source { continue } diff --git a/htlcswitch/hop/forwarding_info.go b/htlcswitch/hop/forwarding_info.go new file mode 100644 index 00000000..54b3274c --- /dev/null +++ b/htlcswitch/hop/forwarding_info.go @@ -0,0 +1,29 @@ +package hop + +import ( + "github.com/lightningnetwork/lnd/lnwire" +) + +// ForwardingInfo contains all the information that is necessary to forward and +// incoming HTLC to the next hop encoded within a valid HopIterator instance. +// Forwarding links are to use this information to authenticate the information +// received within the incoming HTLC, to ensure that the prior hop didn't +// tamper with the end-to-end routing information at all. +type ForwardingInfo struct { + // Network is the target blockchain network that the HTLC will travel + // over next. + Network Network + + // NextHop is the channel ID of the next hop. The received HTLC should + // be forwarded to this particular channel in order to continue the + // end-to-end route. + NextHop lnwire.ShortChannelID + + // AmountToForward is the amount of milli-satoshis that the receiving + // node should forward to the next hop. + AmountToForward lnwire.MilliSatoshi + + // OutgoingCTLV is the specified value of the CTLV timelock to be used + // in the outgoing HTLC. + OutgoingCTLV uint32 +} diff --git a/htlcswitch/hop/network.go b/htlcswitch/hop/network.go new file mode 100644 index 00000000..6f121642 --- /dev/null +++ b/htlcswitch/hop/network.go @@ -0,0 +1,28 @@ +package hop + +// Network indicates the blockchain network that is intended to be the next hop +// for a forwarded HTLC. The existence of this field within the ForwardingInfo +// struct enables the ability for HTLC to cross chain-boundaries at will. +type Network uint8 + +const ( + // BitcoinNetwork denotes that an HTLC is to be forwarded along the + // Bitcoin link with the specified short channel ID. + BitcoinNetwork Network = iota + + // LitecoinNetwork denotes that an HTLC is to be forwarded along the + // Litecoin link with the specified short channel ID. + LitecoinNetwork +) + +// String returns the string representation of the target Network. +func (c Network) String() string { + switch c { + case BitcoinNetwork: + return "Bitcoin" + case LitecoinNetwork: + return "Litecoin" + default: + return "Kekcoin" + } +} diff --git a/htlcswitch/hop/payload.go b/htlcswitch/hop/payload.go new file mode 100644 index 00000000..1c7e563b --- /dev/null +++ b/htlcswitch/hop/payload.go @@ -0,0 +1,75 @@ +package hop + +import ( + "encoding/binary" + "io" + + "github.com/lightningnetwork/lightning-onion" + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/record" + "github.com/lightningnetwork/lnd/tlv" +) + +// Payload encapsulates all information delivered to a hop in an onion payload. +// A Hop can represent either a TLV or legacy payload. The primary forwarding +// instruction can be accessed via ForwardingInfo, and additional records can be +// accessed by other member functions. +type Payload struct { + // FwdInfo holds the basic parameters required for HTLC forwarding, e.g. + // amount, cltv, and next hop. + FwdInfo ForwardingInfo +} + +// NewLegacyPayload builds a Payload from the amount, cltv, and next hop +// parameters provided by leegacy onion payloads. +func NewLegacyPayload(f *sphinx.HopData) *Payload { + nextHop := binary.BigEndian.Uint64(f.NextAddress[:]) + + return &Payload{ + FwdInfo: ForwardingInfo{ + Network: BitcoinNetwork, + NextHop: lnwire.NewShortChanIDFromInt(nextHop), + AmountToForward: lnwire.MilliSatoshi(f.ForwardAmount), + OutgoingCTLV: f.OutgoingCltv, + }, + } +} + +// NewPayloadFromReader builds a new Hop from the passed io.Reader. The reader +// should correspond to the bytes encapsulated in a TLV onion payload. +func NewPayloadFromReader(r io.Reader) (*Payload, error) { + var ( + cid uint64 + amt uint64 + cltv uint32 + ) + + tlvStream, err := tlv.NewStream( + record.NewAmtToFwdRecord(&amt), + record.NewLockTimeRecord(&cltv), + record.NewNextHopIDRecord(&cid), + ) + if err != nil { + return nil, err + } + + err = tlvStream.Decode(r) + if err != nil { + return nil, err + } + + return &Payload{ + FwdInfo: ForwardingInfo{ + Network: BitcoinNetwork, + NextHop: lnwire.NewShortChanIDFromInt(cid), + AmountToForward: lnwire.MilliSatoshi(amt), + OutgoingCTLV: cltv, + }, + }, nil +} + +// ForwardingInfo returns the basic parameters required for HTLC forwarding, +// e.g. amount, cltv, and next hop. +func (h *Payload) ForwardingInfo() ForwardingInfo { + return h.FwdInfo +} diff --git a/htlcswitch/hop/type.go b/htlcswitch/hop/type.go new file mode 100644 index 00000000..a167d10e --- /dev/null +++ b/htlcswitch/hop/type.go @@ -0,0 +1,13 @@ +package hop + +import "github.com/lightningnetwork/lnd/lnwire" + +var ( + // Exit is a special "hop" denoting that an incoming HTLC is meant to + // pay finally to the receiving node. + Exit lnwire.ShortChannelID + + // Source is a sentinel "hop" denoting that an incoming HTLC is + // initiated by our own switch. + Source lnwire.ShortChannelID +) diff --git a/htlcswitch/iterator.go b/htlcswitch/iterator.go index f201129e..9dfe3a1a 100644 --- a/htlcswitch/iterator.go +++ b/htlcswitch/iterator.go @@ -2,82 +2,15 @@ package htlcswitch import ( "bytes" - "encoding/binary" "fmt" "io" "github.com/btcsuite/btcd/btcec" "github.com/lightningnetwork/lightning-onion" + "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/lnwire" - "github.com/lightningnetwork/lnd/record" - "github.com/lightningnetwork/lnd/tlv" ) -// NetworkHop indicates the blockchain network that is intended to be the next -// hop for a forwarded HTLC. The existence of this field within the -// ForwardingInfo struct enables the ability for HTLC to cross chain-boundaries -// at will. -type NetworkHop uint8 - -const ( - // BitcoinHop denotes that an HTLC is to be forwarded along the Bitcoin - // link with the specified short channel ID. - BitcoinHop NetworkHop = iota - - // LitecoinHop denotes that an HTLC is to be forwarded along the - // Litecoin link with the specified short channel ID. - LitecoinHop -) - -// String returns the string representation of the target NetworkHop. -func (c NetworkHop) String() string { - switch c { - case BitcoinHop: - return "Bitcoin" - case LitecoinHop: - return "Litecoin" - default: - return "Kekcoin" - } -} - -var ( - // exitHop is a special "hop" which denotes that an incoming HTLC is - // meant to pay finally to the receiving node. - exitHop lnwire.ShortChannelID - - // sourceHop is a sentinel value denoting that an incoming HTLC is - // initiated by our own switch. - sourceHop lnwire.ShortChannelID -) - -// ForwardingInfo contains all the information that is necessary to forward and -// incoming HTLC to the next hop encoded within a valid HopIterator instance. -// Forwarding links are to use this information to authenticate the information -// received within the incoming HTLC, to ensure that the prior hop didn't -// tamper with the end-to-end routing information at all. -type ForwardingInfo struct { - // Network is the target blockchain network that the HTLC will travel - // over next. - Network NetworkHop - - // NextHop is the channel ID of the next hop. The received HTLC should - // be forwarded to this particular channel in order to continue the - // end-to-end route. - NextHop lnwire.ShortChannelID - - // AmountToForward is the amount of milli-satoshis that the receiving - // node should forward to the next hop. - AmountToForward lnwire.MilliSatoshi - - // OutgoingCTLV is the specified value of the CTLV timelock to be used - // in the outgoing HTLC. - OutgoingCTLV uint32 - - // TODO(roasbeef): modify sphinx logic to not just discard the - // remaining bytes, instead should include the rest as excess -} - // HopIterator is an interface that abstracts away the routing information // included in HTLC's which includes the entirety of the payment path of an // HTLC. This interface provides two basic method which carry out: how to @@ -89,7 +22,7 @@ type HopIterator interface { // Additionally, the information encoded within the returned // ForwardingInfo is to be used by each hop to authenticate the // information given to it by the prior hop. - ForwardingInstructions() (ForwardingInfo, error) + ForwardingInstructions() (hop.ForwardingInfo, error) // ExtraOnionBlob returns the additional EOB data (if available). ExtraOnionBlob() []byte @@ -146,64 +79,35 @@ func (r *sphinxHopIterator) EncodeNextHop(w io.Writer) error { // hop to authenticate the information given to it by the prior hop. // // NOTE: Part of the HopIterator interface. -func (r *sphinxHopIterator) ForwardingInstructions() (ForwardingInfo, error) { - var ( - nextHop lnwire.ShortChannelID - amt uint64 - cltv uint32 - ) +func (r *sphinxHopIterator) ForwardingInstructions() ( + hop.ForwardingInfo, error) { switch r.processedPacket.Payload.Type { // If this is the legacy payload, then we'll extract the information // directly from the pre-populated ForwardingInstructions field. case sphinx.PayloadLegacy: fwdInst := r.processedPacket.ForwardingInstructions + p := hop.NewLegacyPayload(fwdInst) - switch r.processedPacket.Action { - case sphinx.ExitNode: - nextHop = exitHop - case sphinx.MoreHops: - s := binary.BigEndian.Uint64(fwdInst.NextAddress[:]) - nextHop = lnwire.NewShortChanIDFromInt(s) - } - - amt = fwdInst.ForwardAmount - cltv = fwdInst.OutgoingCltv + return p.ForwardingInfo(), nil // Otherwise, if this is the TLV payload, then we'll make a new stream // to decode only what we need to make routing decisions. case sphinx.PayloadTLV: - var cid uint64 - - tlvStream, err := tlv.NewStream( - record.NewAmtToFwdRecord(&amt), - record.NewLockTimeRecord(&cltv), - record.NewNextHopIDRecord(&cid), - ) - if err != nil { - return ForwardingInfo{}, err - } - - err = tlvStream.Decode(bytes.NewReader( + p, err := hop.NewPayloadFromReader(bytes.NewReader( r.processedPacket.Payload.Payload, )) if err != nil { - return ForwardingInfo{}, err + return hop.ForwardingInfo{}, err } - nextHop = lnwire.NewShortChanIDFromInt(cid) + return p.ForwardingInfo(), nil default: - return ForwardingInfo{}, fmt.Errorf("unknown sphinx payload "+ - "type: %v", r.processedPacket.Payload.Type) + return hop.ForwardingInfo{}, fmt.Errorf("unknown "+ + "sphinx payload type: %v", + r.processedPacket.Payload.Type) } - - return ForwardingInfo{ - Network: BitcoinHop, - NextHop: nextHop, - AmountToForward: lnwire.MilliSatoshi(amt), - OutgoingCTLV: cltv, - }, nil } // ExtraOnionBlob returns the additional EOB data (if available). diff --git a/htlcswitch/iterator_test.go b/htlcswitch/iterator_test.go index ae6940e5..08d02439 100644 --- a/htlcswitch/iterator_test.go +++ b/htlcswitch/iterator_test.go @@ -7,6 +7,7 @@ import ( "github.com/davecgh/go-spew/spew" sphinx "github.com/lightningnetwork/lightning-onion" + "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/tlv" @@ -29,7 +30,7 @@ func TestSphinxHopIteratorForwardingInstructions(t *testing.T) { // Next, we'll make the hop forwarding information that we should // extract each type, no matter the payload type. nextAddrInt := binary.BigEndian.Uint64(hopData.NextAddress[:]) - expectedFwdInfo := ForwardingInfo{ + expectedFwdInfo := hop.ForwardingInfo{ NextHop: lnwire.NewShortChanIDFromInt(nextAddrInt), AmountToForward: lnwire.MilliSatoshi(hopData.ForwardAmount), OutgoingCTLV: hopData.OutgoingCltv, @@ -53,7 +54,7 @@ func TestSphinxHopIteratorForwardingInstructions(t *testing.T) { var testCases = []struct { sphinxPacket *sphinx.ProcessedPacket - expectedFwdInfo ForwardingInfo + expectedFwdInfo hop.ForwardingInfo }{ // A regular legacy payload that signals more hops. { diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 661b8a92..f1e1cf24 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -16,6 +16,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/htlcswitch/hodl" + "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/invoices" "github.com/lightningnetwork/lnd/lnpeer" @@ -436,8 +437,8 @@ func (l *channelLink) Start() error { // off point, since all indexes below that are committed. This action // is only performed if the link's final short channel ID has been // assigned, otherwise we would try to trim the htlcs belonging to the - // all-zero, sourceHop ID. - if l.ShortChanID() != sourceHop { + // all-zero, hop.Source ID. + if l.ShortChanID() != hop.Source { localHtlcIndex, err := l.channel.NextLocalHtlcIndex() if err != nil { return fmt.Errorf("unable to retrieve next local "+ @@ -535,7 +536,7 @@ func (l *channelLink) WaitForShutdown() { // the all-zero source ID, meaning that the channel has had its ID finalized. func (l *channelLink) EligibleToForward() bool { return l.channel.RemoteNextRevocation() != nil && - l.ShortChanID() != sourceHop + l.ShortChanID() != hop.Source } // sampleNetworkFee samples the current fee rate on the network to get into the @@ -961,7 +962,7 @@ func (l *channelLink) htlcManager() { // only attempt to resolve packages if our short chan id indicates that // the channel is not pending, otherwise we should have no htlcs to // reforward. - if l.ShortChanID() != sourceHop { + if l.ShortChanID() != hop.Source { if err := l.resolveFwdPkgs(); err != nil { l.fail(LinkFailureError{code: ErrInternalError}, "unable to resolve fwd pkgs: %v", err) @@ -2075,7 +2076,7 @@ func (l *channelLink) UpdateShortChanID() (lnwire.ShortChannelID, error) { if err != nil { l.errorf("unable to refresh short_chan_id for chan_id=%v: %v", chanID, err) - return sourceHop, err + return hop.Source, err } sid := l.channel.ShortChanID() @@ -2674,7 +2675,7 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, } switch fwdInfo.NextHop { - case exitHop: + case hop.Exit: updated, err := l.processExitHop( pd, obfuscator, fwdInfo, heightNow, chanIterator.ExtraOnionBlob(), @@ -2849,7 +2850,7 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, // processExitHop handles an htlc for which this link is the exit hop. It // returns a boolean indicating whether the commitment tx needs an update. func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor, - obfuscator ErrorEncrypter, fwdInfo ForwardingInfo, + obfuscator ErrorEncrypter, fwdInfo hop.ForwardingInfo, heightNow uint32, eob []byte) (bool, error) { // If hodl.ExitSettle is requested, we will not validate the final hop's diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 3c337c16..99889a5f 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -26,6 +26,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/htlcswitch/hodl" + "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnpeer" "github.com/lightningnetwork/lnd/lntypes" @@ -1936,7 +1937,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { } addPkt := htlcPacket{ htlc: htlc, - incomingChanID: sourceHop, + incomingChanID: hop.Source, incomingHTLCID: 0, obfuscator: NewMockObfuscator(), } @@ -2016,7 +2017,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { } addPkt = htlcPacket{ htlc: htlc, - incomingChanID: sourceHop, + incomingChanID: hop.Source, incomingHTLCID: 1, obfuscator: NewMockObfuscator(), } @@ -2534,7 +2535,7 @@ func genAddsAndCircuits(numHtlcs int, htlc *lnwire.UpdateAddHTLC) ( for i := 0; i < numHtlcs; i++ { addPkt := htlcPacket{ htlc: htlc, - incomingChanID: sourceHop, + incomingChanID: hop.Source, incomingHTLCID: uint64(i), obfuscator: NewMockObfuscator(), } @@ -4307,10 +4308,10 @@ func generateHtlcAndInvoice(t *testing.T, htlcAmt := lnwire.NewMSatFromSatoshis(10000) htlcExpiry := testStartingHeight + testInvoiceCltvExpiry - hops := []ForwardingInfo{ + hops := []hop.ForwardingInfo{ { - Network: BitcoinHop, - NextHop: exitHop, + Network: hop.BitcoinNetwork, + NextHop: hop.Exit, AmountToForward: htlcAmt, OutgoingCTLV: uint32(htlcExpiry), }, diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index 34651b5e..b76ff51f 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -23,6 +23,7 @@ import ( "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/contractcourt" + "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/invoices" "github.com/lightningnetwork/lnd/lnpeer" @@ -268,14 +269,16 @@ func (s *mockServer) QuitSignal() <-chan struct{} { // mockHopIterator represents the test version of hop iterator which instead // of encrypting the path in onion blob just stores the path as a list of hops. type mockHopIterator struct { - hops []ForwardingInfo + hops []hop.ForwardingInfo } -func newMockHopIterator(hops ...ForwardingInfo) HopIterator { +func newMockHopIterator(hops ...hop.ForwardingInfo) HopIterator { return &mockHopIterator{hops: hops} } -func (r *mockHopIterator) ForwardingInstructions() (ForwardingInfo, error) { +func (r *mockHopIterator) ForwardingInstructions() ( + hop.ForwardingInfo, error) { + h := r.hops[0] r.hops = r.hops[1:] return h, nil @@ -300,7 +303,7 @@ func (r *mockHopIterator) EncodeNextHop(w io.Writer) error { } for _, hop := range r.hops { - if err := hop.encode(w); err != nil { + if err := encodeFwdInfo(w, &hop); err != nil { return err } } @@ -308,7 +311,7 @@ func (r *mockHopIterator) EncodeNextHop(w io.Writer) error { return nil } -func (f *ForwardingInfo) encode(w io.Writer) error { +func encodeFwdInfo(w io.Writer, f *hop.ForwardingInfo) error { if _, err := w.Write([]byte{byte(f.Network)}); err != nil { return err } @@ -429,10 +432,10 @@ func (p *mockIteratorDecoder) DecodeHopIterator(r io.Reader, rHash []byte, } hopLength := binary.BigEndian.Uint32(b[:]) - hops := make([]ForwardingInfo, hopLength) + hops := make([]hop.ForwardingInfo, hopLength) for i := uint32(0); i < hopLength; i++ { - f := &ForwardingInfo{} - if err := f.decode(r); err != nil { + f := &hop.ForwardingInfo{} + if err := decodeFwdInfo(r, f); err != nil { return nil, lnwire.CodeTemporaryChannelFailure } @@ -480,12 +483,12 @@ func (p *mockIteratorDecoder) DecodeHopIterators(id []byte, return resps, nil } -func (f *ForwardingInfo) decode(r io.Reader) error { +func decodeFwdInfo(r io.Reader, f *hop.ForwardingInfo) error { var net [1]byte if _, err := r.Read(net[:]); err != nil { return err } - f.Network = NetworkHop(net[0]) + f.Network = hop.Network(net[0]) if err := binary.Read(r, binary.BigEndian, &f.NextHop); err != nil { return err diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index bdc50fe5..286dc72d 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -16,6 +16,7 @@ import ( "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/contractcourt" + "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" @@ -354,7 +355,7 @@ func (s *Switch) GetPaymentResult(paymentID uint64, paymentHash lntypes.Hash, nChan <-chan *networkResult err error outKey = CircuitKey{ - ChanID: sourceHop, + ChanID: hop.Source, HtlcID: paymentID, } ) @@ -428,7 +429,7 @@ func (s *Switch) SendHTLC(firstHop lnwire.ShortChannelID, paymentID uint64, // this stage it means that packet haven't left boundaries of our // system and something wrong happened. packet := &htlcPacket{ - incomingChanID: sourceHop, + incomingChanID: hop.Source, incomingHTLCID: paymentID, outgoingChanID: firstHop, htlc: htlc, @@ -513,7 +514,7 @@ func (s *Switch) forward(packet *htlcPacket) error { return ErrDuplicateAdd case len(actions.Fails) == 1: - if packet.incomingChanID == sourceHop { + if packet.incomingChanID == hop.Source { return err } @@ -1031,14 +1032,14 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { case *lnwire.UpdateAddHTLC: // Check if the node is set to reject all onward HTLCs and also make // sure that HTLC is not from the source node. - if s.cfg.RejectHTLC && packet.incomingChanID != sourceHop { + if s.cfg.RejectHTLC && packet.incomingChanID != hop.Source { failure := &lnwire.FailChannelDisabled{} addErr := fmt.Errorf("unable to forward any htlcs") return s.failAddPacket(packet, failure, addErr) } - if packet.incomingChanID == sourceHop { + if packet.incomingChanID == hop.Source { // A blank incomingChanID indicates that this is // a pending user-initiated payment. return s.handleLocalDispatch(packet) @@ -1080,7 +1081,7 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { // If the link doesn't yet have a source chan ID, then // we'll skip it as well. - case link.ShortChanID() == sourceHop: + case link.ShortChanID() == hop.Source: continue } @@ -1222,7 +1223,7 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { // // TODO(roasbeef): only do this once link actually // fully settles? - localHTLC := packet.incomingChanID == sourceHop + localHTLC := packet.incomingChanID == hop.Source if !localHTLC { s.fwdEventMtx.Lock() s.pendingFwdingEvents = append( @@ -1241,7 +1242,7 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { // A blank IncomingChanID in a circuit indicates that it is a pending // user-initiated payment. - if packet.incomingChanID == sourceHop { + if packet.incomingChanID == hop.Source { return s.handleLocalDispatch(packet) } @@ -1798,7 +1799,7 @@ func (s *Switch) reforwardResponses() error { shortChanID := openChannel.ShortChanID() // Locally-initiated payments never need reforwarding. - if shortChanID == sourceHop { + if shortChanID == hop.Source { continue } @@ -1994,7 +1995,7 @@ func (s *Switch) AddLink(link ChannelLink) error { } shortChanID := link.ShortChanID() - if shortChanID == sourceHop { + if shortChanID == hop.Source { log.Infof("Adding pending link chan_id=%v, short_chan_id=%v", chanID, shortChanID) @@ -2157,7 +2158,7 @@ func (s *Switch) UpdateShortChanID(chanID lnwire.ChannelID) error { } // Reject any blank short channel ids. - if shortChanID == sourceHop { + if shortChanID == hop.Source { return fmt.Errorf("refusing trivial short_chan_id for chan_id=%v"+ "live link", chanID) } diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index 50a73a23..65017002 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -25,6 +25,7 @@ import ( "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/contractcourt" + "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnpeer" @@ -596,7 +597,9 @@ func generatePayment(invoiceAmt, htlcAmt lnwire.MilliSatoshi, timelock uint32, } // generateRoute generates the path blob by given array of peers. -func generateRoute(hops ...ForwardingInfo) ([lnwire.OnionPacketSize]byte, error) { +func generateRoute(hops ...hop.ForwardingInfo) ( + [lnwire.OnionPacketSize]byte, error) { + var blob [lnwire.OnionPacketSize]byte if len(hops) == 0 { return blob, errors.New("empty path") @@ -635,16 +638,17 @@ type threeHopNetwork struct { // also the time lock value needed to route an HTLC with the target amount over // the specified path. func generateHops(payAmt lnwire.MilliSatoshi, startingHeight uint32, - path ...*channelLink) (lnwire.MilliSatoshi, uint32, []ForwardingInfo) { + path ...*channelLink) (lnwire.MilliSatoshi, uint32, + []hop.ForwardingInfo) { totalTimelock := startingHeight runningAmt := payAmt - hops := make([]ForwardingInfo, len(path)) + hops := make([]hop.ForwardingInfo, len(path)) for i := len(path) - 1; i >= 0; i-- { // If this is the last hop, then the next hop is the special // "exit node". Otherwise, we look to the "prior" hop. - nextHop := exitHop + nextHop := hop.Exit if i != len(path)-1 { nextHop = path[i+1].channel.ShortChanID() } @@ -679,8 +683,8 @@ func generateHops(payAmt lnwire.MilliSatoshi, startingHeight uint32, amount = runningAmt - fee } - hops[i] = ForwardingInfo{ - Network: BitcoinHop, + hops[i] = hop.ForwardingInfo{ + Network: hop.BitcoinNetwork, NextHop: nextHop, AmountToForward: amount, OutgoingCTLV: timeLock, @@ -731,7 +735,7 @@ func waitForPayFuncResult(payFunc func() error, d time.Duration) error { // * from Alice to Carol through the Bob // * from Alice to some another peer through the Bob func makePayment(sendingPeer, receivingPeer lnpeer.Peer, - firstHop lnwire.ShortChannelID, hops []ForwardingInfo, + firstHop lnwire.ShortChannelID, hops []hop.ForwardingInfo, invoiceAmt, htlcAmt lnwire.MilliSatoshi, timelock uint32) *paymentResponse { @@ -765,7 +769,7 @@ func makePayment(sendingPeer, receivingPeer lnpeer.Peer, // preparePayment creates an invoice at the receivingPeer and returns a function // that, when called, launches the payment from the sendingPeer. func preparePayment(sendingPeer, receivingPeer lnpeer.Peer, - firstHop lnwire.ShortChannelID, hops []ForwardingInfo, + firstHop lnwire.ShortChannelID, hops []hop.ForwardingInfo, invoiceAmt, htlcAmt lnwire.MilliSatoshi, timelock uint32) (*channeldb.Invoice, func() error, error) { @@ -1246,7 +1250,7 @@ func (n *twoHopNetwork) stop() { } func (n *twoHopNetwork) makeHoldPayment(sendingPeer, receivingPeer lnpeer.Peer, - firstHop lnwire.ShortChannelID, hops []ForwardingInfo, + firstHop lnwire.ShortChannelID, hops []hop.ForwardingInfo, invoiceAmt, htlcAmt lnwire.MilliSatoshi, timelock uint32, preimage lntypes.Preimage) chan error {