mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-01-19 05:45:21 +01:00
routing: prune vertex, not ege after repeated FeeInsufficientErrors
In this commit, we modify the way we handle FeeInsufficientErrors to more aggressively route around nodes that repeatedly return the same error to us. This will ensure we skip older nodes on the network which are running a buggier older version of lnd. Eventually most nodes will upgrade to this new version, making this change less needed. We also update the existing test to properly use a multi-hop route to ensure that we route around the offending node.
This commit is contained in:
parent
aa7f83d72e
commit
a6ffe999c6
@ -1724,12 +1724,12 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte, *Route
|
|||||||
// We'll now check to see if we've already
|
// We'll now check to see if we've already
|
||||||
// reported a fee related failure for this
|
// reported a fee related failure for this
|
||||||
// node. If so, then we'll actually prune out
|
// node. If so, then we'll actually prune out
|
||||||
// the edge for now.
|
// the vertex for now.
|
||||||
chanID := update.ShortChannelID
|
chanID := update.ShortChannelID
|
||||||
_, ok := errFailedFeeChans[chanID]
|
_, ok := errFailedFeeChans[chanID]
|
||||||
if ok {
|
if ok {
|
||||||
pruneEdgeFailure(
|
pruneVertexFailure(
|
||||||
paySession, route, errSource,
|
paySession, route, errSource, false,
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -297,7 +297,7 @@ func TestSendPaymentErrorRepeatedFeeInsufficient(t *testing.T) {
|
|||||||
// to luo ji for 100 satoshis.
|
// to luo ji for 100 satoshis.
|
||||||
var payHash [32]byte
|
var payHash [32]byte
|
||||||
payment := LightningPayment{
|
payment := LightningPayment{
|
||||||
Target: ctx.aliases["luoji"],
|
Target: ctx.aliases["sophon"],
|
||||||
Amount: lnwire.NewMSatFromSatoshis(1000),
|
Amount: lnwire.NewMSatFromSatoshis(1000),
|
||||||
PaymentHash: payHash,
|
PaymentHash: payHash,
|
||||||
}
|
}
|
||||||
@ -306,9 +306,9 @@ func TestSendPaymentErrorRepeatedFeeInsufficient(t *testing.T) {
|
|||||||
copy(preImage[:], bytes.Repeat([]byte{9}, 32))
|
copy(preImage[:], bytes.Repeat([]byte{9}, 32))
|
||||||
|
|
||||||
// We'll also fetch the first outgoing channel edge from roasbeef to
|
// We'll also fetch the first outgoing channel edge from roasbeef to
|
||||||
// luo ji. We'll obtain this as we'll need to to generate the
|
// son goku. We'll obtain this as we'll need to to generate the
|
||||||
// FeeInsufficient error that we'll send back.
|
// FeeInsufficient error that we'll send back.
|
||||||
chanID := uint64(689530843)
|
chanID := uint64(3495345)
|
||||||
_, _, edgeUpateToFail, err := ctx.graph.FetchChannelEdgesByID(chanID)
|
_, _, edgeUpateToFail, err := ctx.graph.FetchChannelEdgesByID(chanID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to fetch chan id: %v", err)
|
t.Fatalf("unable to fetch chan id: %v", err)
|
||||||
@ -324,24 +324,21 @@ func TestSendPaymentErrorRepeatedFeeInsufficient(t *testing.T) {
|
|||||||
FeeRate: uint32(edgeUpateToFail.FeeProportionalMillionths),
|
FeeRate: uint32(edgeUpateToFail.FeeProportionalMillionths),
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceNode := ctx.router.selfNode
|
// The error will be returned by Son Goku.
|
||||||
|
sourceNode := ctx.aliases["songoku"]
|
||||||
|
|
||||||
// We'll now modify the SendToSwitch method to return an error for the
|
// We'll now modify the SendToSwitch method to return an error for the
|
||||||
// outgoing channel to luo ji. This will be a fee related error, so it
|
// outgoing channel to Son goku. This will be a fee related error, so
|
||||||
// should only cause the edge to be pruned after the second attempt.
|
// it should only cause the edge to be pruned after the second attempt.
|
||||||
ctx.router.cfg.SendToSwitch = func(n [33]byte,
|
ctx.router.cfg.SendToSwitch = func(n [33]byte,
|
||||||
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
||||||
|
|
||||||
if bytes.Equal(ctx.aliases["luoji"].SerializeCompressed(), n[:]) {
|
if bytes.Equal(sourceNode.SerializeCompressed(), n[:]) {
|
||||||
pub, err := sourceNode.PubKey()
|
|
||||||
if err != nil {
|
|
||||||
return preImage, err
|
|
||||||
}
|
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: pub,
|
ErrorSource: sourceNode,
|
||||||
|
|
||||||
// Within our error, we'll add a channel update
|
// Within our error, we'll add a channel update
|
||||||
// which is meant to refelct he new fee
|
// which is meant to reflect he new fee
|
||||||
// schedule for the node/channel.
|
// schedule for the node/channel.
|
||||||
FailureMessage: &lnwire.FailFeeInsufficient{
|
FailureMessage: &lnwire.FailFeeInsufficient{
|
||||||
Update: errChanUpdate,
|
Update: errChanUpdate,
|
||||||
@ -371,8 +368,8 @@ func TestSendPaymentErrorRepeatedFeeInsufficient(t *testing.T) {
|
|||||||
preImage[:], paymentPreImage[:])
|
preImage[:], paymentPreImage[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// The route should have satoshi as the first hop.
|
// The route should have pham nuwen as the first hop.
|
||||||
if route.Hops[0].Channel.Node.Alias != "satoshi" {
|
if route.Hops[0].Channel.Node.Alias != "phamnuwen" {
|
||||||
t.Fatalf("route should go through satoshi as first hop, "+
|
t.Fatalf("route should go through satoshi as first hop, "+
|
||||||
"instead passes through: %v",
|
"instead passes through: %v",
|
||||||
route.Hops[0].Channel.Node.Alias)
|
route.Hops[0].Channel.Node.Alias)
|
||||||
|
Loading…
Reference in New Issue
Block a user