lnd: add basic HtlcSwitch logic for forwarding L2 payments
This commit is contained in:
parent
9b29fa3a52
commit
af7cfd6c8b
@ -41,7 +41,7 @@ type link struct {
|
|||||||
type htlcPacket struct {
|
type htlcPacket struct {
|
||||||
dest wire.ShaHash
|
dest wire.ShaHash
|
||||||
|
|
||||||
htlc lnwire.Message
|
msg lnwire.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
// HtlcSwitch is a central messaging bus for all incoming/outgoing HTLC's.
|
// HtlcSwitch is a central messaging bus for all incoming/outgoing HTLC's.
|
||||||
@ -65,6 +65,8 @@ type htlcSwitch struct {
|
|||||||
|
|
||||||
outgoingPayments chan *htlcPacket
|
outgoingPayments chan *htlcPacket
|
||||||
|
|
||||||
|
htlcPlex chan *htlcPacket
|
||||||
|
|
||||||
// TODO(roasbeef): messaging chan to/from upper layer (routing - L3)
|
// TODO(roasbeef): messaging chan to/from upper layer (routing - L3)
|
||||||
|
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
@ -77,6 +79,7 @@ func newHtlcSwitch() *htlcSwitch {
|
|||||||
chanIndex: make(map[wire.OutPoint]*link),
|
chanIndex: make(map[wire.OutPoint]*link),
|
||||||
interfaces: make(map[wire.ShaHash][]*link),
|
interfaces: make(map[wire.ShaHash][]*link),
|
||||||
linkControl: make(chan interface{}),
|
linkControl: make(chan interface{}),
|
||||||
|
htlcPlex: make(chan *htlcPacket, htlcQueueSize),
|
||||||
outgoingPayments: make(chan *htlcPacket, 20),
|
outgoingPayments: make(chan *htlcPacket, 20),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,6 +110,16 @@ func (h *htlcSwitch) Stop() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendHTLC queues a HTLC packet for forwarding over the designated interface.
|
||||||
|
// In the event that the interface has insufficient capacity for the payment,
|
||||||
|
// an error is returned. Additionally, if the interface cannot be found, an
|
||||||
|
// alternative error is returned.
|
||||||
|
func (h *htlcSwitch) SendHTLC(htlcPkt *htlcPacket) error {
|
||||||
|
// TODO(roasbeef): hook in errors
|
||||||
|
h.outgoingPayments <- htlcPkt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// htlcForwarder is responsible for optimally forwarding (and possibly
|
// htlcForwarder is responsible for optimally forwarding (and possibly
|
||||||
// fragmenting) incoming/outgoing HTLC's amongst all active interfaces and
|
// fragmenting) incoming/outgoing HTLC's amongst all active interfaces and
|
||||||
// their links.
|
// their links.
|
||||||
@ -114,7 +127,37 @@ func (h *htlcSwitch) htlcForwarder() {
|
|||||||
out:
|
out:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-h.outgoingPayments:
|
case htlcPkt := <-h.outgoingPayments:
|
||||||
|
chanInterface, ok := h.interfaces[htlcPkt.dest]
|
||||||
|
if !ok {
|
||||||
|
hswcLog.Errorf("unable to locate link %x", htlcPkt.dest[:])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
wireMsg := htlcPkt.msg.(*lnwire.HTLCAddRequest)
|
||||||
|
amt := btcutil.Amount(wireMsg.Amount)
|
||||||
|
hswcLog.Debugf("attempting to send %v to %v", amt,
|
||||||
|
hex.EncodeToString(htlcPkt.dest[:]))
|
||||||
|
|
||||||
|
for _, link := range chanInterface {
|
||||||
|
// TODO(roasbeef): implement HTLC fragmentation
|
||||||
|
if link.availableBandwidth >= amt {
|
||||||
|
hswcLog.Debugf("selected %v for payment of %v to %x",
|
||||||
|
link.chanPoint, amt, htlcPkt.dest[:])
|
||||||
|
|
||||||
|
wireMsg.ChannelPoint = link.chanPoint
|
||||||
|
link.linkChan <- wireMsg
|
||||||
|
// TODO(roasbeef): update link info on
|
||||||
|
// timeout/settle
|
||||||
|
link.availableBandwidth -= amt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if wireMsg.ChannelPoint == nil {
|
||||||
|
hswcLog.Errorf("unable to send payment, " +
|
||||||
|
"insufficient capacity")
|
||||||
|
}
|
||||||
|
case <-h.htlcPlex:
|
||||||
case <-h.quit:
|
case <-h.quit:
|
||||||
break out
|
break out
|
||||||
}
|
}
|
||||||
@ -230,13 +273,15 @@ type registerLinkMsg struct {
|
|||||||
// RegisterLink requests the htlcSwitch to register a new active link. The new
|
// RegisterLink requests the htlcSwitch to register a new active link. The new
|
||||||
// link encapsulates an active channel.
|
// link encapsulates an active channel.
|
||||||
func (h *htlcSwitch) RegisterLink(p *peer, linkInfo *channeldb.ChannelSnapshot,
|
func (h *htlcSwitch) RegisterLink(p *peer, linkInfo *channeldb.ChannelSnapshot,
|
||||||
linkChan chan lnwire.Message) {
|
linkChan chan lnwire.Message) chan *htlcPacket {
|
||||||
|
|
||||||
done := make(chan struct{}, 1)
|
done := make(chan struct{}, 1)
|
||||||
req := ®isterLinkMsg{p, linkInfo, linkChan, done}
|
req := ®isterLinkMsg{p, linkInfo, linkChan, done}
|
||||||
h.linkControl <- req
|
h.linkControl <- req
|
||||||
|
|
||||||
<-done
|
<-done
|
||||||
|
|
||||||
|
return h.htlcPlex
|
||||||
}
|
}
|
||||||
|
|
||||||
// unregisterLinkMsg is a message which requests the active ink be unregistered.
|
// unregisterLinkMsg is a message which requests the active ink be unregistered.
|
||||||
|
Loading…
Reference in New Issue
Block a user