peer: set and use aux htlc validator
When instantiating the lightning channel we now pass in the created HTLC validator. This validator simply performs a bandwidth check and errors out if that is insufficient.
This commit is contained in:
1 file changed
+110
@@ -52,6 +52,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/pool"
|
"github.com/lightningnetwork/lnd/pool"
|
||||||
"github.com/lightningnetwork/lnd/protofsm"
|
"github.com/lightningnetwork/lnd/protofsm"
|
||||||
"github.com/lightningnetwork/lnd/queue"
|
"github.com/lightningnetwork/lnd/queue"
|
||||||
|
"github.com/lightningnetwork/lnd/routing/route"
|
||||||
"github.com/lightningnetwork/lnd/subscribe"
|
"github.com/lightningnetwork/lnd/subscribe"
|
||||||
"github.com/lightningnetwork/lnd/ticker"
|
"github.com/lightningnetwork/lnd/ticker"
|
||||||
"github.com/lightningnetwork/lnd/tlv"
|
"github.com/lightningnetwork/lnd/tlv"
|
||||||
@@ -1146,6 +1147,16 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
p.cfg.AuxTrafficShaper.WhenSome(
|
||||||
|
func(ts htlcswitch.AuxTrafficShaper) {
|
||||||
|
val := p.createHtlcValidator(dbChan, ts)
|
||||||
|
chanOpts = append(
|
||||||
|
chanOpts,
|
||||||
|
lnwallet.WithAuxHtlcValidator(val),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
lnChan, err := lnwallet.NewLightningChannel(
|
lnChan, err := lnwallet.NewLightningChannel(
|
||||||
p.cfg.Signer, dbChan, p.cfg.SigPool, chanOpts...,
|
p.cfg.Signer, dbChan, p.cfg.SigPool, chanOpts...,
|
||||||
)
|
)
|
||||||
@@ -5259,6 +5270,15 @@ func (p *Brontide) addActiveChannel(c *lnpeer.NewChannel) error {
|
|||||||
chanOpts = append(chanOpts, lnwallet.WithAuxResolver(s))
|
chanOpts = append(chanOpts, lnwallet.WithAuxResolver(s))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
p.cfg.AuxTrafficShaper.WhenSome(
|
||||||
|
func(ts htlcswitch.AuxTrafficShaper) {
|
||||||
|
val := p.createHtlcValidator(c.OpenChannel, ts)
|
||||||
|
chanOpts = append(
|
||||||
|
chanOpts, lnwallet.WithAuxHtlcValidator(val),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// If not already active, we'll add this channel to the set of active
|
// If not already active, we'll add this channel to the set of active
|
||||||
// channels, so we can look it up later easily according to its channel
|
// channels, so we can look it up later easily according to its channel
|
||||||
// ID.
|
// ID.
|
||||||
@@ -5465,6 +5485,96 @@ func (p *Brontide) scaleTimeout(timeout time.Duration) time.Duration {
|
|||||||
return timeout
|
return timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// auxHtlcValidator implements lnwallet.AuxHtlcValidator by checking HTLC
|
||||||
|
// bandwidth against the traffic shaper.
|
||||||
|
type auxHtlcValidator struct {
|
||||||
|
peer *Brontide
|
||||||
|
dbChan *channeldb.OpenChannel
|
||||||
|
ts htlcswitch.AuxTrafficShaper
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateHtlc performs final aux balance validation before an HTLC is added
|
||||||
|
// to the channel state. It calls into the traffic shaper's PaymentBandwidth
|
||||||
|
// method to check external balance against the most up-to-date channel state,
|
||||||
|
// preventing race conditions where multiple HTLCs could be approved based on
|
||||||
|
// stale bandwidth.
|
||||||
|
func (v *auxHtlcValidator) ValidateHtlc(amount,
|
||||||
|
linkBandwidth lnwire.MilliSatoshi,
|
||||||
|
customRecords lnwire.CustomRecords,
|
||||||
|
view lnwallet.AuxHtlcView) error {
|
||||||
|
|
||||||
|
// Get the short channel ID for logging.
|
||||||
|
scid := v.dbChan.ShortChannelID
|
||||||
|
|
||||||
|
// Extract the HTLC custom records to pass to the traffic shaper.
|
||||||
|
var htlcBlob fn.Option[tlv.Blob]
|
||||||
|
if len(customRecords) > 0 {
|
||||||
|
blob, err := customRecords.Serialize()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to serialize "+
|
||||||
|
"custom records: %w", err)
|
||||||
|
}
|
||||||
|
htlcBlob = fn.Some(blob)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the funding and commitment blobs for this channel.
|
||||||
|
fundingBlob := v.dbChan.CustomBlob
|
||||||
|
commitmentBlob := v.dbChan.LocalCommitment.CustomBlob
|
||||||
|
|
||||||
|
// Check if this channel should be handled by the traffic shaper. If
|
||||||
|
// not, we skip the aux validation entirely and allow the HTLC to
|
||||||
|
// proceed through normal validation.
|
||||||
|
shouldHandle, err := v.ts.ShouldHandleTraffic(
|
||||||
|
scid, fundingBlob, htlcBlob,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("traffic shaper failed to decide "+
|
||||||
|
"whether to handle traffic: %w", err)
|
||||||
|
}
|
||||||
|
if !shouldHandle {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
peer := route.NewVertex(v.peer.IdentityKey())
|
||||||
|
|
||||||
|
// Call the traffic shaper's PaymentBandwidth method with the current
|
||||||
|
// state. This performs the same bandwidth checks as during
|
||||||
|
// pathfinding/forwarding, but against the absolute latest channel
|
||||||
|
// state.
|
||||||
|
//
|
||||||
|
// The linkBandwidth is provided by the channel and represents the
|
||||||
|
// current available balance, which is used by the traffic shaper to
|
||||||
|
// ensure we don't dip below channel reserves.
|
||||||
|
bandwidth, err := v.ts.PaymentBandwidth(
|
||||||
|
fundingBlob, htlcBlob, commitmentBlob,
|
||||||
|
linkBandwidth, amount, view, peer,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("traffic shaper bandwidth check "+
|
||||||
|
"failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if amount > bandwidth {
|
||||||
|
return fmt.Errorf("insufficient aux bandwidth: "+
|
||||||
|
"need %v, have %v (scid=%v)", amount,
|
||||||
|
bandwidth, scid)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createHtlcValidator creates an HTLC validator that performs final aux balance
|
||||||
|
// validation before HTLCs are added to the channel state.
|
||||||
|
func (p *Brontide) createHtlcValidator(dbChan *channeldb.OpenChannel,
|
||||||
|
ts htlcswitch.AuxTrafficShaper) lnwallet.AuxHtlcValidator {
|
||||||
|
|
||||||
|
return &auxHtlcValidator{
|
||||||
|
peer: p,
|
||||||
|
dbChan: dbChan,
|
||||||
|
ts: ts,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CoopCloseUpdates is a struct used to communicate updates for an active close
|
// CoopCloseUpdates is a struct used to communicate updates for an active close
|
||||||
// to the caller.
|
// to the caller.
|
||||||
type CoopCloseUpdates struct {
|
type CoopCloseUpdates struct {
|
||||||
|
|||||||
Reference in new issue
Block a user