mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-05-18 15:50:06 +02:00
htlcswitch: thread through packet's inbound wire records
For calculating the available auxiliary bandwidth of a channel, we need access to the inbound custom wire records of the HTLC packet, which might contain auxiliary information about the worth of the HTLC packet apart from the BTC value being transported.
This commit is contained in:
parent
117c6bc781
commit
a2e78c3984
@ -272,10 +272,10 @@ type ChannelLink interface {
|
|||||||
// in order to signal to the source of the HTLC, the policy consistency
|
// in order to signal to the source of the HTLC, the policy consistency
|
||||||
// issue.
|
// issue.
|
||||||
CheckHtlcForward(payHash [32]byte, incomingAmt lnwire.MilliSatoshi,
|
CheckHtlcForward(payHash [32]byte, incomingAmt lnwire.MilliSatoshi,
|
||||||
amtToForward lnwire.MilliSatoshi,
|
amtToForward lnwire.MilliSatoshi, incomingTimeout,
|
||||||
incomingTimeout, outgoingTimeout uint32,
|
outgoingTimeout uint32, inboundFee models.InboundFee,
|
||||||
inboundFee models.InboundFee,
|
heightNow uint32, scid lnwire.ShortChannelID,
|
||||||
heightNow uint32, scid lnwire.ShortChannelID) *LinkError
|
customRecords lnwire.CustomRecords) *LinkError
|
||||||
|
|
||||||
// CheckHtlcTransit should return a nil error if the passed HTLC details
|
// CheckHtlcTransit should return a nil error if the passed HTLC details
|
||||||
// satisfy the current channel policy. Otherwise, a LinkError with a
|
// satisfy the current channel policy. Otherwise, a LinkError with a
|
||||||
@ -283,7 +283,8 @@ type ChannelLink interface {
|
|||||||
// the violation. This call is intended to be used for locally initiated
|
// the violation. This call is intended to be used for locally initiated
|
||||||
// payments for which there is no corresponding incoming htlc.
|
// payments for which there is no corresponding incoming htlc.
|
||||||
CheckHtlcTransit(payHash [32]byte, amt lnwire.MilliSatoshi,
|
CheckHtlcTransit(payHash [32]byte, amt lnwire.MilliSatoshi,
|
||||||
timeout uint32, heightNow uint32) *LinkError
|
timeout uint32, heightNow uint32,
|
||||||
|
customRecords lnwire.CustomRecords) *LinkError
|
||||||
|
|
||||||
// Stats return the statistics of channel link. Number of updates,
|
// Stats return the statistics of channel link. Number of updates,
|
||||||
// total sent/received milli-satoshis.
|
// total sent/received milli-satoshis.
|
||||||
|
@ -3233,11 +3233,11 @@ func (l *channelLink) UpdateForwardingPolicy(
|
|||||||
// issue.
|
// issue.
|
||||||
//
|
//
|
||||||
// NOTE: Part of the ChannelLink interface.
|
// NOTE: Part of the ChannelLink interface.
|
||||||
func (l *channelLink) CheckHtlcForward(payHash [32]byte,
|
func (l *channelLink) CheckHtlcForward(payHash [32]byte, incomingHtlcAmt,
|
||||||
incomingHtlcAmt, amtToForward lnwire.MilliSatoshi,
|
amtToForward lnwire.MilliSatoshi, incomingTimeout,
|
||||||
incomingTimeout, outgoingTimeout uint32,
|
outgoingTimeout uint32, inboundFee models.InboundFee,
|
||||||
inboundFee models.InboundFee,
|
heightNow uint32, originalScid lnwire.ShortChannelID,
|
||||||
heightNow uint32, originalScid lnwire.ShortChannelID) *LinkError {
|
customRecords lnwire.CustomRecords) *LinkError {
|
||||||
|
|
||||||
l.RLock()
|
l.RLock()
|
||||||
policy := l.cfg.FwrdingPolicy
|
policy := l.cfg.FwrdingPolicy
|
||||||
@ -3286,7 +3286,7 @@ func (l *channelLink) CheckHtlcForward(payHash [32]byte,
|
|||||||
// Check whether the outgoing htlc satisfies the channel policy.
|
// Check whether the outgoing htlc satisfies the channel policy.
|
||||||
err := l.canSendHtlc(
|
err := l.canSendHtlc(
|
||||||
policy, payHash, amtToForward, outgoingTimeout, heightNow,
|
policy, payHash, amtToForward, outgoingTimeout, heightNow,
|
||||||
originalScid,
|
originalScid, customRecords,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -3322,8 +3322,8 @@ func (l *channelLink) CheckHtlcForward(payHash [32]byte,
|
|||||||
// the violation. This call is intended to be used for locally initiated
|
// the violation. This call is intended to be used for locally initiated
|
||||||
// payments for which there is no corresponding incoming htlc.
|
// payments for which there is no corresponding incoming htlc.
|
||||||
func (l *channelLink) CheckHtlcTransit(payHash [32]byte,
|
func (l *channelLink) CheckHtlcTransit(payHash [32]byte,
|
||||||
amt lnwire.MilliSatoshi, timeout uint32,
|
amt lnwire.MilliSatoshi, timeout uint32, heightNow uint32,
|
||||||
heightNow uint32) *LinkError {
|
customRecords lnwire.CustomRecords) *LinkError {
|
||||||
|
|
||||||
l.RLock()
|
l.RLock()
|
||||||
policy := l.cfg.FwrdingPolicy
|
policy := l.cfg.FwrdingPolicy
|
||||||
@ -3334,6 +3334,7 @@ func (l *channelLink) CheckHtlcTransit(payHash [32]byte,
|
|||||||
// to occur.
|
// to occur.
|
||||||
return l.canSendHtlc(
|
return l.canSendHtlc(
|
||||||
policy, payHash, amt, timeout, heightNow, hop.Source,
|
policy, payHash, amt, timeout, heightNow, hop.Source,
|
||||||
|
customRecords,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3341,7 +3342,8 @@ func (l *channelLink) CheckHtlcTransit(payHash [32]byte,
|
|||||||
// the channel's amount and time lock constraints.
|
// the channel's amount and time lock constraints.
|
||||||
func (l *channelLink) canSendHtlc(policy models.ForwardingPolicy,
|
func (l *channelLink) canSendHtlc(policy models.ForwardingPolicy,
|
||||||
payHash [32]byte, amt lnwire.MilliSatoshi, timeout uint32,
|
payHash [32]byte, amt lnwire.MilliSatoshi, timeout uint32,
|
||||||
heightNow uint32, originalScid lnwire.ShortChannelID) *LinkError {
|
heightNow uint32, originalScid lnwire.ShortChannelID,
|
||||||
|
customRecords lnwire.CustomRecords) *LinkError {
|
||||||
|
|
||||||
// As our first sanity check, we'll ensure that the passed HTLC isn't
|
// As our first sanity check, we'll ensure that the passed HTLC isn't
|
||||||
// too small for the next hop. If so, then we'll cancel the HTLC
|
// too small for the next hop. If so, then we'll cancel the HTLC
|
||||||
|
@ -6243,9 +6243,9 @@ func TestCheckHtlcForward(t *testing.T) {
|
|||||||
var hash [32]byte
|
var hash [32]byte
|
||||||
|
|
||||||
t.Run("satisfied", func(t *testing.T) {
|
t.Run("satisfied", func(t *testing.T) {
|
||||||
result := link.CheckHtlcForward(hash, 1500, 1000,
|
result := link.CheckHtlcForward(
|
||||||
200, 150, models.InboundFee{}, 0,
|
hash, 1500, 1000, 200, 150, models.InboundFee{}, 0,
|
||||||
lnwire.ShortChannelID{},
|
lnwire.ShortChannelID{}, nil,
|
||||||
)
|
)
|
||||||
if result != nil {
|
if result != nil {
|
||||||
t.Fatalf("expected policy to be satisfied")
|
t.Fatalf("expected policy to be satisfied")
|
||||||
@ -6253,9 +6253,9 @@ func TestCheckHtlcForward(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("below minhtlc", func(t *testing.T) {
|
t.Run("below minhtlc", func(t *testing.T) {
|
||||||
result := link.CheckHtlcForward(hash, 100, 50,
|
result := link.CheckHtlcForward(
|
||||||
200, 150, models.InboundFee{}, 0,
|
hash, 100, 50, 200, 150, models.InboundFee{}, 0,
|
||||||
lnwire.ShortChannelID{},
|
lnwire.ShortChannelID{}, nil,
|
||||||
)
|
)
|
||||||
if _, ok := result.WireMessage().(*lnwire.FailAmountBelowMinimum); !ok {
|
if _, ok := result.WireMessage().(*lnwire.FailAmountBelowMinimum); !ok {
|
||||||
t.Fatalf("expected FailAmountBelowMinimum failure code")
|
t.Fatalf("expected FailAmountBelowMinimum failure code")
|
||||||
@ -6263,9 +6263,9 @@ func TestCheckHtlcForward(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("above maxhtlc", func(t *testing.T) {
|
t.Run("above maxhtlc", func(t *testing.T) {
|
||||||
result := link.CheckHtlcForward(hash, 1500, 1200,
|
result := link.CheckHtlcForward(
|
||||||
200, 150, models.InboundFee{}, 0,
|
hash, 1500, 1200, 200, 150, models.InboundFee{}, 0,
|
||||||
lnwire.ShortChannelID{},
|
lnwire.ShortChannelID{}, nil,
|
||||||
)
|
)
|
||||||
if _, ok := result.WireMessage().(*lnwire.FailTemporaryChannelFailure); !ok {
|
if _, ok := result.WireMessage().(*lnwire.FailTemporaryChannelFailure); !ok {
|
||||||
t.Fatalf("expected FailTemporaryChannelFailure failure code")
|
t.Fatalf("expected FailTemporaryChannelFailure failure code")
|
||||||
@ -6273,9 +6273,9 @@ func TestCheckHtlcForward(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("insufficient fee", func(t *testing.T) {
|
t.Run("insufficient fee", func(t *testing.T) {
|
||||||
result := link.CheckHtlcForward(hash, 1005, 1000,
|
result := link.CheckHtlcForward(
|
||||||
200, 150, models.InboundFee{}, 0,
|
hash, 1005, 1000, 200, 150, models.InboundFee{}, 0,
|
||||||
lnwire.ShortChannelID{},
|
lnwire.ShortChannelID{}, nil,
|
||||||
)
|
)
|
||||||
if _, ok := result.WireMessage().(*lnwire.FailFeeInsufficient); !ok {
|
if _, ok := result.WireMessage().(*lnwire.FailFeeInsufficient); !ok {
|
||||||
t.Fatalf("expected FailFeeInsufficient failure code")
|
t.Fatalf("expected FailFeeInsufficient failure code")
|
||||||
@ -6288,17 +6288,17 @@ func TestCheckHtlcForward(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
result := link.CheckHtlcForward(
|
result := link.CheckHtlcForward(
|
||||||
hash, 100005, 100000, 200,
|
hash, 100005, 100000, 200, 150, models.InboundFee{}, 0,
|
||||||
150, models.InboundFee{}, 0, lnwire.ShortChannelID{},
|
lnwire.ShortChannelID{}, nil,
|
||||||
)
|
)
|
||||||
_, ok := result.WireMessage().(*lnwire.FailFeeInsufficient)
|
_, ok := result.WireMessage().(*lnwire.FailFeeInsufficient)
|
||||||
require.True(t, ok, "expected FailFeeInsufficient failure code")
|
require.True(t, ok, "expected FailFeeInsufficient failure code")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("expiry too soon", func(t *testing.T) {
|
t.Run("expiry too soon", func(t *testing.T) {
|
||||||
result := link.CheckHtlcForward(hash, 1500, 1000,
|
result := link.CheckHtlcForward(
|
||||||
200, 150, models.InboundFee{}, 190,
|
hash, 1500, 1000, 200, 150, models.InboundFee{}, 190,
|
||||||
lnwire.ShortChannelID{},
|
lnwire.ShortChannelID{}, nil,
|
||||||
)
|
)
|
||||||
if _, ok := result.WireMessage().(*lnwire.FailExpiryTooSoon); !ok {
|
if _, ok := result.WireMessage().(*lnwire.FailExpiryTooSoon); !ok {
|
||||||
t.Fatalf("expected FailExpiryTooSoon failure code")
|
t.Fatalf("expected FailExpiryTooSoon failure code")
|
||||||
@ -6306,9 +6306,9 @@ func TestCheckHtlcForward(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("incorrect cltv expiry", func(t *testing.T) {
|
t.Run("incorrect cltv expiry", func(t *testing.T) {
|
||||||
result := link.CheckHtlcForward(hash, 1500, 1000,
|
result := link.CheckHtlcForward(
|
||||||
200, 190, models.InboundFee{}, 0,
|
hash, 1500, 1000, 200, 190, models.InboundFee{}, 0,
|
||||||
lnwire.ShortChannelID{},
|
lnwire.ShortChannelID{}, nil,
|
||||||
)
|
)
|
||||||
if _, ok := result.WireMessage().(*lnwire.FailIncorrectCltvExpiry); !ok {
|
if _, ok := result.WireMessage().(*lnwire.FailIncorrectCltvExpiry); !ok {
|
||||||
t.Fatalf("expected FailIncorrectCltvExpiry failure code")
|
t.Fatalf("expected FailIncorrectCltvExpiry failure code")
|
||||||
@ -6318,9 +6318,9 @@ func TestCheckHtlcForward(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("cltv expiry too far in the future", func(t *testing.T) {
|
t.Run("cltv expiry too far in the future", func(t *testing.T) {
|
||||||
// Check that expiry isn't too far in the future.
|
// Check that expiry isn't too far in the future.
|
||||||
result := link.CheckHtlcForward(hash, 1500, 1000,
|
result := link.CheckHtlcForward(
|
||||||
10200, 10100, models.InboundFee{}, 0,
|
hash, 1500, 1000, 10200, 10100, models.InboundFee{}, 0,
|
||||||
lnwire.ShortChannelID{},
|
lnwire.ShortChannelID{}, nil,
|
||||||
)
|
)
|
||||||
if _, ok := result.WireMessage().(*lnwire.FailExpiryTooFar); !ok {
|
if _, ok := result.WireMessage().(*lnwire.FailExpiryTooFar); !ok {
|
||||||
t.Fatalf("expected FailExpiryTooFar failure code")
|
t.Fatalf("expected FailExpiryTooFar failure code")
|
||||||
@ -6330,9 +6330,11 @@ func TestCheckHtlcForward(t *testing.T) {
|
|||||||
t.Run("inbound fee satisfied", func(t *testing.T) {
|
t.Run("inbound fee satisfied", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
result := link.CheckHtlcForward(hash, 1000+10-2-1, 1000,
|
result := link.CheckHtlcForward(
|
||||||
200, 150, models.InboundFee{Base: -2, Rate: -1_000},
|
hash, 1000+10-2-1, 1000, 200, 150,
|
||||||
0, lnwire.ShortChannelID{})
|
models.InboundFee{Base: -2, Rate: -1_000},
|
||||||
|
0, lnwire.ShortChannelID{}, nil,
|
||||||
|
)
|
||||||
if result != nil {
|
if result != nil {
|
||||||
t.Fatalf("expected policy to be satisfied")
|
t.Fatalf("expected policy to be satisfied")
|
||||||
}
|
}
|
||||||
@ -6341,9 +6343,11 @@ func TestCheckHtlcForward(t *testing.T) {
|
|||||||
t.Run("inbound fee insufficient", func(t *testing.T) {
|
t.Run("inbound fee insufficient", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
result := link.CheckHtlcForward(hash, 1000+10-10-101-1, 1000,
|
result := link.CheckHtlcForward(
|
||||||
|
hash, 1000+10-10-101-1, 1000,
|
||||||
200, 150, models.InboundFee{Base: -10, Rate: -100_000},
|
200, 150, models.InboundFee{Base: -10, Rate: -100_000},
|
||||||
0, lnwire.ShortChannelID{})
|
0, lnwire.ShortChannelID{}, nil,
|
||||||
|
)
|
||||||
|
|
||||||
msg := result.WireMessage()
|
msg := result.WireMessage()
|
||||||
if _, ok := msg.(*lnwire.FailFeeInsufficient); !ok {
|
if _, ok := msg.(*lnwire.FailFeeInsufficient); !ok {
|
||||||
|
@ -846,14 +846,14 @@ func (f *mockChannelLink) UpdateForwardingPolicy(_ models.ForwardingPolicy) {
|
|||||||
}
|
}
|
||||||
func (f *mockChannelLink) CheckHtlcForward([32]byte, lnwire.MilliSatoshi,
|
func (f *mockChannelLink) CheckHtlcForward([32]byte, lnwire.MilliSatoshi,
|
||||||
lnwire.MilliSatoshi, uint32, uint32, models.InboundFee, uint32,
|
lnwire.MilliSatoshi, uint32, uint32, models.InboundFee, uint32,
|
||||||
lnwire.ShortChannelID) *LinkError {
|
lnwire.ShortChannelID, lnwire.CustomRecords) *LinkError {
|
||||||
|
|
||||||
return f.checkHtlcForwardResult
|
return f.checkHtlcForwardResult
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *mockChannelLink) CheckHtlcTransit(payHash [32]byte,
|
func (f *mockChannelLink) CheckHtlcTransit(payHash [32]byte,
|
||||||
amt lnwire.MilliSatoshi, timeout uint32,
|
amt lnwire.MilliSatoshi, timeout uint32,
|
||||||
heightNow uint32) *LinkError {
|
heightNow uint32, _ lnwire.CustomRecords) *LinkError {
|
||||||
|
|
||||||
return f.checkHtlcTransitResult
|
return f.checkHtlcTransitResult
|
||||||
}
|
}
|
||||||
|
@ -917,6 +917,7 @@ func (s *Switch) getLocalLink(pkt *htlcPacket, htlc *lnwire.UpdateAddHTLC) (
|
|||||||
currentHeight := atomic.LoadUint32(&s.bestHeight)
|
currentHeight := atomic.LoadUint32(&s.bestHeight)
|
||||||
htlcErr := link.CheckHtlcTransit(
|
htlcErr := link.CheckHtlcTransit(
|
||||||
htlc.PaymentHash, htlc.Amount, htlc.Expiry, currentHeight,
|
htlc.PaymentHash, htlc.Amount, htlc.Expiry, currentHeight,
|
||||||
|
htlc.CustomRecords,
|
||||||
)
|
)
|
||||||
if htlcErr != nil {
|
if htlcErr != nil {
|
||||||
log.Errorf("Link %v policy for local forward not "+
|
log.Errorf("Link %v policy for local forward not "+
|
||||||
@ -2887,10 +2888,9 @@ func (s *Switch) handlePacketAdd(packet *htlcPacket,
|
|||||||
failure = link.CheckHtlcForward(
|
failure = link.CheckHtlcForward(
|
||||||
htlc.PaymentHash, packet.incomingAmount,
|
htlc.PaymentHash, packet.incomingAmount,
|
||||||
packet.amount, packet.incomingTimeout,
|
packet.amount, packet.incomingTimeout,
|
||||||
packet.outgoingTimeout,
|
packet.outgoingTimeout, packet.inboundFee,
|
||||||
packet.inboundFee,
|
currentHeight, packet.originalOutgoingChanID,
|
||||||
currentHeight,
|
htlc.CustomRecords,
|
||||||
packet.originalOutgoingChanID,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user