diff --git a/channeldb/graph_test.go b/channeldb/graph_test.go index 27ed7ba5..378391ec 100644 --- a/channeldb/graph_test.go +++ b/channeldb/graph_test.go @@ -729,6 +729,14 @@ func TestEdgeInfoUpdates(t *testing.T) { // Create an edge and add it to the db. edgeInfo, edge1, edge2 := createChannelEdge(db, node1, node2) + + // Make sure inserting the policy at this point, before the edge info + // is added, will fail. + if err := graph.UpdateEdgePolicy(edge1); err != ErrEdgeNotFound { + t.Fatalf("expected ErrEdgeNotFound, got: %v", err) + } + + // Add the edge info. if err := graph.AddChannelEdge(edgeInfo); err != nil { t.Fatalf("unable to create channel edge: %v", err) } diff --git a/routing/router.go b/routing/router.go index c33f3ff1..cdb8d53a 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1125,8 +1125,6 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error { } r.rejectMtx.RUnlock() - channelID := lnwire.NewShortChanIDFromInt(msg.ChannelID) - // We make sure to hold the mutex for this channel ID, // such that no other goroutine is concurrently doing // database accesses for the same channel ID. @@ -1142,6 +1140,15 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error { } + // If the channel doesn't exist in our database, we cannot + // apply the updated policy. + if !exists { + return newErrf(ErrIgnored, "Ignoring update "+ + "(flags=%v|%v) for unknown chan_id=%v", + msg.MessageFlags, msg.ChannelFlags, + msg.ChannelID) + } + // As edges are directional edge node has a unique policy for // the direction of the edge they control. Therefore we first // check if we already have the most up to date information for @@ -1174,36 +1181,6 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error { } } - if !exists && !r.cfg.AssumeChannelValid { - // Before we can update the channel information, we'll - // ensure that the target channel is still open by - // querying the utxo-set for its existence. - chanPoint, fundingTxOut, err := r.fetchChanPoint( - &channelID, - ) - if err != nil { - r.rejectMtx.Lock() - r.rejectCache[msg.ChannelID] = struct{}{} - r.rejectMtx.Unlock() - - return errors.Errorf("unable to fetch chan "+ - "point for chan_id=%v: %v", - msg.ChannelID, err) - } - _, err = r.cfg.Chain.GetUtxo( - chanPoint, fundingTxOut.PkScript, - channelID.BlockHeight, - ) - if err != nil { - r.rejectMtx.Lock() - r.rejectCache[msg.ChannelID] = struct{}{} - r.rejectMtx.Unlock() - - return errors.Errorf("unable to fetch utxo for "+ - "chan_id=%v: %v", msg.ChannelID, err) - } - } - // Now that we know this isn't a stale update, we'll apply the // new edge policy to the proper directional edge within the // channel graph. diff --git a/routing/router_test.go b/routing/router_test.go index e39ed313..c79af2b2 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -14,7 +14,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/davecgh/go-spew/spew" - "github.com/lightningnetwork/lightning-onion" + sphinx "github.com/lightningnetwork/lightning-onion" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lnwire" @@ -1025,6 +1025,86 @@ func TestIgnoreNodeAnnouncement(t *testing.T) { } } +// TestIgnoreChannelEdgePolicyForUnknownChannel checks that a router will +// ignore a channel policy for a channel not in the graph. +func TestIgnoreChannelEdgePolicyForUnknownChannel(t *testing.T) { + t.Parallel() + + const startingBlockHeight = 101 + + // Setup an initially empty network. + testChannels := []*testChannel{} + testGraph, err := createTestGraphFromChannels(testChannels) + if err != nil { + t.Fatalf("unable to create graph: %v", err) + } + defer testGraph.cleanUp() + + ctx, cleanUp, err := createTestCtxFromGraphInstance( + startingBlockHeight, testGraph, + ) + if err != nil { + t.Fatalf("unable to create router: %v", err) + } + defer cleanUp() + + var pub1 [33]byte + copy(pub1[:], priv1.PubKey().SerializeCompressed()) + + var pub2 [33]byte + copy(pub2[:], priv2.PubKey().SerializeCompressed()) + + // Add the edge between the two unknown nodes to the graph, and check + // that the nodes are found after the fact. + fundingTx, _, chanID, err := createChannelEdge( + ctx, bitcoinKey1.SerializeCompressed(), + bitcoinKey2.SerializeCompressed(), 10000, 500, + ) + if err != nil { + t.Fatalf("unable to create channel edge: %v", err) + } + fundingBlock := &wire.MsgBlock{ + Transactions: []*wire.MsgTx{fundingTx}, + } + ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight) + + edge := &channeldb.ChannelEdgeInfo{ + ChannelID: chanID.ToUint64(), + NodeKey1Bytes: pub1, + NodeKey2Bytes: pub2, + BitcoinKey1Bytes: pub1, + BitcoinKey2Bytes: pub2, + AuthProof: nil, + } + edgePolicy := &channeldb.ChannelEdgePolicy{ + SigBytes: testSig.Serialize(), + ChannelID: edge.ChannelID, + LastUpdate: testTime, + TimeLockDelta: 10, + MinHTLC: 1, + FeeBaseMSat: 10, + FeeProportionalMillionths: 10000, + } + + // Attempt to update the edge. This should be ignored, since the edge + // is not yet added to the router. + err = ctx.router.UpdateEdge(edgePolicy) + if !IsError(err, ErrIgnored) { + t.Fatalf("expected to get ErrIgnore, instead got: %v", err) + } + + // Add the edge. + if err := ctx.router.AddEdge(edge); err != nil { + t.Fatalf("expected to be able to add edge to the channel graph,"+ + " even though the vertexes were unknown: %v.", err) + } + + // Now updating the edge policy should succeed. + if err := ctx.router.UpdateEdge(edgePolicy); err != nil { + t.Fatalf("unable to update edge policy: %v", err) + } +} + // TestAddEdgeUnknownVertexes tests that if an edge is added that contains two // vertexes which we don't know of, the edge should be available for use // regardless. This is due to the fact that we don't actually need node