htlcswitch: relay experimental endorsement signal with update_add_htlc
This commit is contained in:
9 files changed
+134
-11
No files matched your search
@@ -30,6 +30,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/queue"
|
||||
"github.com/lightningnetwork/lnd/record"
|
||||
"github.com/lightningnetwork/lnd/ticker"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
)
|
||||
@@ -285,6 +286,10 @@ type ChannelLinkConfig struct {
|
||||
// MaxFeeExposure is the threshold in milli-satoshis after which we'll
|
||||
// restrict the flow of HTLCs and fee updates.
|
||||
MaxFeeExposure lnwire.MilliSatoshi
|
||||
|
||||
// ShouldFwdExpEndorsement is a closure that indicates whether the link
|
||||
// should forward experimental endorsement signals.
|
||||
ShouldFwdExpEndorsement func() bool
|
||||
}
|
||||
|
||||
// channelLink is the service which drives a channel's commitment update
|
||||
@@ -3651,6 +3656,13 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg) {
|
||||
continue
|
||||
}
|
||||
|
||||
endorseValue := l.experimentalEndorsement(
|
||||
record.CustomSet(add.CustomRecords),
|
||||
)
|
||||
endorseType := uint64(
|
||||
lnwire.ExperimentalEndorsementType,
|
||||
)
|
||||
|
||||
switch fwdPkg.State {
|
||||
case channeldb.FwdStateProcessed:
|
||||
// This add was not forwarded on the previous
|
||||
@@ -3672,6 +3684,14 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg) {
|
||||
BlindingPoint: fwdInfo.NextBlinding,
|
||||
}
|
||||
|
||||
endorseValue.WhenSome(func(e byte) {
|
||||
custRecords := map[uint64][]byte{
|
||||
endorseType: {e},
|
||||
}
|
||||
|
||||
outgoingAdd.CustomRecords = custRecords
|
||||
})
|
||||
|
||||
// Finally, we'll encode the onion packet for
|
||||
// the _next_ hop using the hop iterator
|
||||
// decoded for the current hop.
|
||||
@@ -3722,6 +3742,12 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg) {
|
||||
BlindingPoint: fwdInfo.NextBlinding,
|
||||
}
|
||||
|
||||
endorseValue.WhenSome(func(e byte) {
|
||||
addMsg.CustomRecords = map[uint64][]byte{
|
||||
endorseType: {e},
|
||||
}
|
||||
})
|
||||
|
||||
// Finally, we'll encode the onion packet for the
|
||||
// _next_ hop using the hop iterator decoded for the
|
||||
// current hop.
|
||||
@@ -3809,6 +3835,46 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg) {
|
||||
l.forwardBatch(replay, switchPackets...)
|
||||
}
|
||||
|
||||
// experimentalEndorsement returns the value to set for our outgoing
|
||||
// experimental endorsement field, and a boolean indicating whether it should
|
||||
// be populated on the outgoing htlc.
|
||||
func (l *channelLink) experimentalEndorsement(
|
||||
customUpdateAdd record.CustomSet) fn.Option[byte] {
|
||||
|
||||
// Only relay experimental signal if we are within the experiment
|
||||
// period.
|
||||
if !l.cfg.ShouldFwdExpEndorsement() {
|
||||
return fn.None[byte]()
|
||||
}
|
||||
|
||||
// If we don't have any custom records or the experimental field is
|
||||
// not set, just forward a zero value.
|
||||
if len(customUpdateAdd) == 0 {
|
||||
return fn.Some[byte](lnwire.ExperimentalUnendorsed)
|
||||
}
|
||||
|
||||
t := uint64(lnwire.ExperimentalEndorsementType)
|
||||
value, set := customUpdateAdd[t]
|
||||
if !set {
|
||||
return fn.Some[byte](lnwire.ExperimentalUnendorsed)
|
||||
}
|
||||
|
||||
// We expect at least one byte for this field, consider it invalid if
|
||||
// it has no data and just forward a zero value.
|
||||
if len(value) == 0 {
|
||||
return fn.Some[byte](lnwire.ExperimentalUnendorsed)
|
||||
}
|
||||
|
||||
// Only forward endorsed if the incoming link is endorsed.
|
||||
if value[0] == lnwire.ExperimentalEndorsed {
|
||||
return fn.Some[byte](lnwire.ExperimentalEndorsed)
|
||||
}
|
||||
|
||||
// Forward as unendorsed otherwise, including cases where we've
|
||||
// received an invalid value that uses more than 3 bits of information.
|
||||
return fn.Some[byte](lnwire.ExperimentalUnendorsed)
|
||||
}
|
||||
|
||||
// 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(add lnwire.UpdateAddHTLC,
|
||||
|
||||
@@ -2245,6 +2245,7 @@ func newSingleLinkTestHarness(t *testing.T, chanAmt,
|
||||
NotifyInactiveLinkEvent: func(wire.OutPoint) {},
|
||||
HtlcNotifier: aliceSwitch.cfg.HtlcNotifier,
|
||||
GetAliases: getAliases,
|
||||
ShouldFwdExpEndorsement: func() bool { return true },
|
||||
}
|
||||
|
||||
aliceLink := NewChannelLink(aliceCfg, aliceLc.channel)
|
||||
@@ -4888,6 +4889,8 @@ func (h *persistentLinkHarness) restartLink(
|
||||
// Instantiate with a long interval, so that we can precisely control
|
||||
// the firing via force feeding.
|
||||
bticker := ticker.NewForce(time.Hour)
|
||||
|
||||
//nolint:lll
|
||||
aliceCfg := ChannelLinkConfig{
|
||||
FwrdingPolicy: globalPolicy,
|
||||
Peer: alicePeer,
|
||||
@@ -4932,6 +4935,7 @@ func (h *persistentLinkHarness) restartLink(
|
||||
HtlcNotifier: h.hSwitch.cfg.HtlcNotifier,
|
||||
SyncStates: syncStates,
|
||||
GetAliases: getAliases,
|
||||
ShouldFwdExpEndorsement: func() bool { return true },
|
||||
}
|
||||
|
||||
aliceLink := NewChannelLink(aliceCfg, aliceChannel)
|
||||
|
||||
@@ -1154,6 +1154,7 @@ func (h *hopNetwork) createChannelLink(server, peer *mockServer,
|
||||
return server.htlcSwitch.ForwardPackets(linkQuit, packets...)
|
||||
}
|
||||
|
||||
//nolint:lll
|
||||
link := NewChannelLink(
|
||||
ChannelLinkConfig{
|
||||
BestHeight: server.htlcSwitch.BestHeight,
|
||||
@@ -1193,6 +1194,7 @@ func (h *hopNetwork) createChannelLink(server, peer *mockServer,
|
||||
NotifyInactiveLinkEvent: func(wire.OutPoint) {},
|
||||
HtlcNotifier: server.htlcSwitch.cfg.HtlcNotifier,
|
||||
GetAliases: getAliases,
|
||||
ShouldFwdExpEndorsement: func() bool { return true },
|
||||
},
|
||||
channel,
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user