github.com/decred/dcrlnd@v0.7.6/routing/router_test.go (about)

     1  package routing
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"image/color"
     7  	"math"
     8  	"math/rand"
     9  	"sync/atomic"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/davecgh/go-spew/spew"
    14  	"github.com/stretchr/testify/mock"
    15  	"github.com/stretchr/testify/require"
    16  
    17  	"github.com/decred/dcrd/chaincfg/chainhash"
    18  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    19  	"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
    20  	"github.com/decred/dcrd/dcrutil/v4"
    21  	"github.com/decred/dcrd/wire"
    22  	"github.com/decred/dcrlnd/chainntnfs"
    23  	"github.com/decred/dcrlnd/channeldb"
    24  	"github.com/decred/dcrlnd/clock"
    25  	"github.com/decred/dcrlnd/htlcswitch"
    26  	lnmock "github.com/decred/dcrlnd/lntest/mock"
    27  	"github.com/decred/dcrlnd/lntest/wait"
    28  	"github.com/decred/dcrlnd/lntypes"
    29  	"github.com/decred/dcrlnd/lnwire"
    30  	"github.com/decred/dcrlnd/record"
    31  	"github.com/decred/dcrlnd/routing/route"
    32  	"github.com/decred/dcrlnd/zpay32"
    33  )
    34  
    35  var uniquePaymentID uint64 = 1 // to be used atomically
    36  
    37  type testCtx struct {
    38  	router *ChannelRouter
    39  
    40  	graph *channeldb.ChannelGraph
    41  
    42  	aliases map[string]route.Vertex
    43  
    44  	privKeys map[string]*secp256k1.PrivateKey
    45  
    46  	channelIDs map[route.Vertex]map[route.Vertex]uint64
    47  
    48  	chain *mockChain
    49  
    50  	chainView *mockChainView
    51  
    52  	notifier *lnmock.ChainNotifier
    53  }
    54  
    55  func (c *testCtx) getChannelIDFromAlias(t *testing.T, a, b string) uint64 {
    56  	vertexA, ok := c.aliases[a]
    57  	require.True(t, ok, "cannot find aliases for %s", a)
    58  
    59  	vertexB, ok := c.aliases[b]
    60  	require.True(t, ok, "cannot find aliases for %s", b)
    61  
    62  	channelIDMap, ok := c.channelIDs[vertexA]
    63  	require.True(t, ok, "cannot find channelID map %s(%s)", vertexA, a)
    64  
    65  	channelID, ok := channelIDMap[vertexB]
    66  	require.True(t, ok, "cannot find channelID using %s(%s)", vertexB, b)
    67  
    68  	return channelID
    69  }
    70  
    71  func (c *testCtx) RestartRouter(t *testing.T) {
    72  	// First, we'll reset the chainView's state as it doesn't persist the
    73  	// filter between restarts.
    74  	c.chainView.Reset()
    75  
    76  	// With the chainView reset, we'll now re-create the router itself, and
    77  	// start it.
    78  	router, err := New(Config{
    79  		Graph:              c.graph,
    80  		Chain:              c.chain,
    81  		ChainView:          c.chainView,
    82  		Payer:              &mockPaymentAttemptDispatcherOld{},
    83  		Control:            makeMockControlTower(),
    84  		ChannelPruneExpiry: time.Hour * 24,
    85  		GraphPruneInterval: time.Hour * 2,
    86  	})
    87  	require.NoError(t, err, "unable to create router")
    88  	require.NoError(t, router.Start(), "unable to start router")
    89  
    90  	// Finally, we'll swap out the pointer in the testCtx with this fresh
    91  	// instance of the router.
    92  	c.router = router
    93  }
    94  
    95  func createTestCtxFromGraphInstance(t *testing.T,
    96  	startingHeight uint32, graphInstance *testGraphInstance,
    97  	strictPruning bool) (*testCtx, func()) {
    98  
    99  	return createTestCtxFromGraphInstanceAssumeValid(
   100  		t, startingHeight, graphInstance, false, strictPruning,
   101  	)
   102  }
   103  
   104  func createTestCtxFromGraphInstanceAssumeValid(t *testing.T,
   105  	startingHeight uint32, graphInstance *testGraphInstance,
   106  	assumeValid bool, strictPruning bool) (*testCtx, func()) {
   107  
   108  	// We'll initialize an instance of the channel router with mock
   109  	// versions of the chain and channel notifier. As we don't need to test
   110  	// any p2p functionality, the peer send and switch send messages won't
   111  	// be populated.
   112  	chain := newMockChain(startingHeight)
   113  	chainView := newMockChainView(chain)
   114  
   115  	pathFindingConfig := PathFindingConfig{
   116  		MinProbability: 0.01,
   117  		AttemptCost:    100,
   118  	}
   119  
   120  	mcConfig := &MissionControlConfig{
   121  		ProbabilityEstimatorCfg: ProbabilityEstimatorCfg{
   122  			PenaltyHalfLife:       time.Hour,
   123  			AprioriHopProbability: 0.9,
   124  			AprioriWeight:         0.5,
   125  		},
   126  	}
   127  
   128  	mc, err := NewMissionControl(
   129  		graphInstance.graphBackend, route.Vertex{}, mcConfig,
   130  	)
   131  	require.NoError(t, err, "failed to create missioncontrol")
   132  	drainMCStoreQueueChan(t, mc.store)
   133  
   134  	sourceNode, err := graphInstance.graph.SourceNode()
   135  	require.NoError(t, err)
   136  	sessionSource := &SessionSource{
   137  		Graph:             graphInstance.graph,
   138  		SourceNode:        sourceNode,
   139  		GetLink:           graphInstance.getLink,
   140  		PathFindingConfig: pathFindingConfig,
   141  		MissionControl:    mc,
   142  	}
   143  
   144  	notifier := &lnmock.ChainNotifier{
   145  		EpochChan: make(chan *chainntnfs.BlockEpoch),
   146  		SpendChan: make(chan *chainntnfs.SpendDetail),
   147  		ConfChan:  make(chan *chainntnfs.TxConfirmation),
   148  	}
   149  
   150  	router, err := New(Config{
   151  		Graph:              graphInstance.graph,
   152  		Chain:              chain,
   153  		ChainView:          chainView,
   154  		Payer:              &mockPaymentAttemptDispatcherOld{},
   155  		Notifier:           notifier,
   156  		Control:            makeMockControlTower(),
   157  		MissionControl:     mc,
   158  		SessionSource:      sessionSource,
   159  		ChannelPruneExpiry: time.Hour * 24,
   160  		GraphPruneInterval: time.Hour * 2,
   161  		GetLink:            graphInstance.getLink,
   162  		NextPaymentID: func() (uint64, error) {
   163  			next := atomic.AddUint64(&uniquePaymentID, 1)
   164  			return next, nil
   165  		},
   166  		PathFindingConfig:   pathFindingConfig,
   167  		LocalOpenChanIDs:    func() (map[uint64]struct{}, error) { return map[uint64]struct{}{}, nil },
   168  		Clock:               clock.NewTestClock(time.Unix(1, 0)),
   169  		AssumeChannelValid:  assumeValid,
   170  		StrictZombiePruning: strictPruning,
   171  	})
   172  	require.NoError(t, err, "unable to create router")
   173  	require.NoError(t, router.Start(), "unable to start router")
   174  
   175  	ctx := &testCtx{
   176  		router:     router,
   177  		graph:      graphInstance.graph,
   178  		aliases:    graphInstance.aliasMap,
   179  		privKeys:   graphInstance.privKeyMap,
   180  		channelIDs: graphInstance.channelIDs,
   181  		chain:      chain,
   182  		chainView:  chainView,
   183  		notifier:   notifier,
   184  	}
   185  
   186  	cleanUp := func() {
   187  		ctx.router.Stop()
   188  	}
   189  
   190  	return ctx, cleanUp
   191  }
   192  
   193  func createTestCtxSingleNode(t *testing.T,
   194  	startingHeight uint32) (*testCtx, func()) {
   195  
   196  	graph, graphBackend, cleanup, err := makeTestGraph(true)
   197  	require.NoError(t, err, "failed to make test graph")
   198  
   199  	sourceNode, err := createTestNode()
   200  	require.NoError(t, err, "failed to create test node")
   201  
   202  	require.NoError(t,
   203  		graph.SetSourceNode(sourceNode), "failed to set source node",
   204  	)
   205  
   206  	graphInstance := &testGraphInstance{
   207  		graph:        graph,
   208  		graphBackend: graphBackend,
   209  		cleanUp:      cleanup,
   210  	}
   211  
   212  	return createTestCtxFromGraphInstance(
   213  		t, startingHeight, graphInstance, false,
   214  	)
   215  }
   216  
   217  func createTestCtxFromFile(t *testing.T,
   218  	startingHeight uint32, testGraph string) (*testCtx, func()) {
   219  
   220  	// We'll attempt to locate and parse out the file
   221  	// that encodes the graph that our tests should be run against.
   222  	graphInstance, err := parseTestGraph(true, testGraph)
   223  	require.NoError(t, err, "unable to create test graph")
   224  
   225  	return createTestCtxFromGraphInstance(
   226  		t, startingHeight, graphInstance, false,
   227  	)
   228  }
   229  
   230  // Add valid signature to channel update simulated as error received from the
   231  // network.
   232  func signErrChanUpdate(t *testing.T, key *secp256k1.PrivateKey,
   233  	errChanUpdate *lnwire.ChannelUpdate) {
   234  
   235  	chanUpdateMsg, err := errChanUpdate.DataToSign()
   236  	require.NoError(t, err, "failed to retrieve data to sign")
   237  
   238  	digest := chainhash.HashB(chanUpdateMsg)
   239  	sig := ecdsa.Sign(key, digest)
   240  
   241  	errChanUpdate.Signature, err = lnwire.NewSigFromSignature(sig)
   242  	require.NoError(t, err, "failed to create new signature")
   243  }
   244  
   245  // TestFindRoutesWithFeeLimit asserts that routes found by the FindRoutes method
   246  // within the channel router contain a total fee less than or equal to the fee
   247  // limit.
   248  func TestFindRoutesWithFeeLimit(t *testing.T) {
   249  	t.Parallel()
   250  
   251  	const startingBlockHeight = 101
   252  	ctx, cleanUp := createTestCtxFromFile(
   253  		t, startingBlockHeight, basicGraphFilePath,
   254  	)
   255  	defer cleanUp()
   256  
   257  	// This test will attempt to find routes from roasbeef to sophon for 100
   258  	// atoms with a fee limit of 10 atoms. There are two routes from
   259  	// roasbeef to sophon:
   260  	//	1. roasbeef -> songoku -> sophon
   261  	//	2. roasbeef -> phamnuwen -> sophon
   262  	// The second route violates our fee limit, so we should only expect to
   263  	// see the first route.
   264  	target := ctx.aliases["sophon"]
   265  	paymentAmt := lnwire.NewMAtomsFromAtoms(100)
   266  	restrictions := &RestrictParams{
   267  		FeeLimit:          lnwire.NewMAtomsFromAtoms(10),
   268  		ProbabilitySource: noProbabilitySource,
   269  		CltvLimit:         math.MaxUint32,
   270  	}
   271  
   272  	route, err := ctx.router.FindRoute(
   273  		ctx.router.selfNode.PubKeyBytes,
   274  		target, paymentAmt, restrictions, nil, nil,
   275  		MinCLTVDelta,
   276  	)
   277  	require.NoError(t, err, "unable to find any routes")
   278  
   279  	require.Falsef(t,
   280  		route.TotalFees() > restrictions.FeeLimit,
   281  		"route exceeded fee limit: %v", spew.Sdump(route),
   282  	)
   283  
   284  	hops := route.Hops
   285  	require.Equal(t, 2, len(hops), "expected 2 hops")
   286  
   287  	require.Equalf(t,
   288  		ctx.aliases["songoku"], hops[0].PubKeyBytes,
   289  		"expected first hop through songoku, got %s",
   290  		getAliasFromPubKey(hops[0].PubKeyBytes, ctx.aliases),
   291  	)
   292  }
   293  
   294  // TestSendPaymentRouteFailureFallback tests that when sending a payment, if
   295  // one of the target routes is seen as unavailable, then the next route in the
   296  // queue is used instead. This process should continue until either a payment
   297  // succeeds, or all routes have been exhausted.
   298  func TestSendPaymentRouteFailureFallback(t *testing.T) {
   299  	t.Parallel()
   300  
   301  	const startingBlockHeight = 101
   302  	ctx, cleanUp := createTestCtxFromFile(
   303  		t, startingBlockHeight, basicGraphFilePath,
   304  	)
   305  	defer cleanUp()
   306  
   307  	// Craft a LightningPayment struct that'll send a payment from roasbeef
   308  	// to luo ji for 1000 atoms, with a maximum of 1000 atoms in fees.
   309  	var payHash lntypes.Hash
   310  	paymentAmt := lnwire.NewMAtomsFromAtoms(1000)
   311  	payment := LightningPayment{
   312  		Target:      ctx.aliases["sophon"],
   313  		Amount:      paymentAmt,
   314  		FeeLimit:    noFeeLimit,
   315  		paymentHash: &payHash,
   316  	}
   317  
   318  	var preImage [32]byte
   319  	copy(preImage[:], bytes.Repeat([]byte{9}, 32))
   320  
   321  	// Get the channel ID.
   322  	roasbeefSongoku := lnwire.NewShortChanIDFromInt(
   323  		ctx.getChannelIDFromAlias(t, "roasbeef", "songoku"),
   324  	)
   325  
   326  	// We'll modify the SendToSwitch method that's been set within the
   327  	// router's configuration to ignore the path that has son goku as the
   328  	// first hop. This should force the router to instead take the
   329  	// the more costly path (through pham nuwen).
   330  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
   331  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
   332  
   333  			if firstHop == roasbeefSongoku {
   334  				return [32]byte{}, htlcswitch.NewForwardingError(
   335  					// TODO(roasbeef): temp node failure
   336  					//  should be?
   337  					&lnwire.FailTemporaryChannelFailure{},
   338  					1,
   339  				)
   340  			}
   341  
   342  			return preImage, nil
   343  		})
   344  
   345  	// Send off the payment request to the router, route through pham nuwen
   346  	// should've been selected as a fall back and succeeded correctly.
   347  	paymentPreImage, route, err := ctx.router.SendPayment(&payment)
   348  	require.NoError(t, err, "unable to send payment")
   349  
   350  	// The route selected should have two hops
   351  	require.Equal(t, 2, len(route.Hops), "incorrect route length")
   352  
   353  	// The preimage should match up with the once created above.
   354  	if !bytes.Equal(paymentPreImage[:], preImage[:]) {
   355  		t.Fatalf("incorrect preimage used: expected %x got %x",
   356  			preImage[:], paymentPreImage[:])
   357  	}
   358  
   359  	// The route should have pham nuwen as the first hop.
   360  	require.Equalf(t,
   361  		ctx.aliases["phamnuwen"], route.Hops[0].PubKeyBytes,
   362  		"route should go through phamnuwen as first hop, instead "+
   363  			"passes through: %v",
   364  		getAliasFromPubKey(route.Hops[0].PubKeyBytes, ctx.aliases),
   365  	)
   366  }
   367  
   368  // TestChannelUpdateValidation tests that a failed payment with an associated
   369  // channel update will only be applied to the graph when the update contains a
   370  // valid signature.
   371  func TestChannelUpdateValidation(t *testing.T) {
   372  	t.Parallel()
   373  
   374  	// Setup a three node network.
   375  	chanCapSat := dcrutil.Amount(100000)
   376  	feeRate := lnwire.MilliAtom(400)
   377  	testChannels := []*testChannel{
   378  		symmetricTestChannel("a", "b", chanCapSat, &testChannelPolicy{
   379  			Expiry:  144,
   380  			FeeRate: feeRate,
   381  			MinHTLC: 1,
   382  			MaxHTLC: lnwire.NewMAtomsFromAtoms(chanCapSat),
   383  		}, 1),
   384  		symmetricTestChannel("b", "c", chanCapSat, &testChannelPolicy{
   385  			Expiry:  144,
   386  			FeeRate: feeRate,
   387  			MinHTLC: 1,
   388  			MaxHTLC: lnwire.NewMAtomsFromAtoms(chanCapSat),
   389  		}, 2),
   390  	}
   391  
   392  	testGraph, err := createTestGraphFromChannels(true, testChannels, "a")
   393  	require.NoError(t, err, "unable to create graph")
   394  	defer testGraph.cleanUp()
   395  
   396  	const startingBlockHeight = 101
   397  	ctx, cleanUp := createTestCtxFromGraphInstance(
   398  		t, startingBlockHeight, testGraph, true,
   399  	)
   400  	defer cleanUp()
   401  
   402  	// Assert that the initially configured fee is retrieved correctly.
   403  	_, policy, _, err := ctx.router.GetChannelByID(
   404  		lnwire.NewShortChanIDFromInt(1))
   405  	require.NoError(t, err, "cannot retrieve channel")
   406  
   407  	require.Equal(t,
   408  		feeRate, policy.FeeProportionalMillionths, "invalid fee",
   409  	)
   410  
   411  	// Setup a route from source a to destination c. The route will be used
   412  	// in a call to SendToRoute. SendToRoute also applies channel updates,
   413  	// but it saves us from including RequestRoute in the test scope too.
   414  	hop1 := ctx.aliases["b"]
   415  	hop2 := ctx.aliases["c"]
   416  	hops := []*route.Hop{
   417  		{
   418  			ChannelID:     1,
   419  			PubKeyBytes:   hop1,
   420  			LegacyPayload: true,
   421  		},
   422  		{
   423  			ChannelID:     2,
   424  			PubKeyBytes:   hop2,
   425  			LegacyPayload: true,
   426  		},
   427  	}
   428  
   429  	rt, err := route.NewRouteFromHops(
   430  		lnwire.MilliAtom(10000), 100,
   431  		ctx.aliases["a"], hops,
   432  	)
   433  	require.NoError(t, err, "unable to create route")
   434  
   435  	// Set up a channel update message with an invalid signature to be
   436  	// returned to the sender.
   437  	var invalidSignature [64]byte
   438  	errChanUpdate := lnwire.ChannelUpdate{
   439  		Signature:      invalidSignature,
   440  		FeeRate:        500,
   441  		ShortChannelID: lnwire.NewShortChanIDFromInt(1),
   442  		Timestamp:      uint32(testTime.Add(time.Minute).Unix()),
   443  	}
   444  
   445  	// We'll modify the SendToSwitch method so that it simulates a failed
   446  	// payment with an error originating from the first hop of the route.
   447  	// The unsigned channel update is attached to the failure message.
   448  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
   449  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
   450  			return [32]byte{}, htlcswitch.NewForwardingError(
   451  				&lnwire.FailFeeInsufficient{
   452  					Update: errChanUpdate,
   453  				},
   454  				1,
   455  			)
   456  		})
   457  
   458  	// The payment parameter is mostly redundant in SendToRoute. Can be left
   459  	// empty for this test.
   460  	var payment lntypes.Hash
   461  
   462  	// Send off the payment request to the router. The specified route
   463  	// should be attempted and the channel update should be received by
   464  	// router and ignored because it is missing a valid signature.
   465  	_, err = ctx.router.SendToRoute(payment, rt)
   466  	require.Error(t, err, "expected route to fail with channel update")
   467  
   468  	_, policy, _, err = ctx.router.GetChannelByID(
   469  		lnwire.NewShortChanIDFromInt(1))
   470  	require.NoError(t, err, "cannot retrieve channel")
   471  
   472  	require.Equal(t,
   473  		feeRate, policy.FeeProportionalMillionths,
   474  		"fee updated without valid signature",
   475  	)
   476  
   477  	// Next, add a signature to the channel update.
   478  	signErrChanUpdate(t, testGraph.privKeyMap["b"], &errChanUpdate)
   479  
   480  	// Retry the payment using the same route as before.
   481  	_, err = ctx.router.SendToRoute(payment, rt)
   482  	if err == nil {
   483  		t.Fatalf("expected route to fail with channel update")
   484  	}
   485  
   486  	// This time a valid signature was supplied and the policy change should
   487  	// have been applied to the graph.
   488  	_, policy, _, err = ctx.router.GetChannelByID(
   489  		lnwire.NewShortChanIDFromInt(1))
   490  	require.NoError(t, err, "cannot retrieve channel")
   491  
   492  	require.Equal(t,
   493  		lnwire.MilliAtom(500), policy.FeeProportionalMillionths,
   494  		"fee not updated even though signature is valid",
   495  	)
   496  }
   497  
   498  // TestSendPaymentErrorRepeatedFeeInsufficient tests that if we receive
   499  // multiple fee related errors from a channel that we're attempting to route
   500  // through, then we'll prune the channel after the second attempt.
   501  func TestSendPaymentErrorRepeatedFeeInsufficient(t *testing.T) {
   502  	t.Parallel()
   503  
   504  	const startingBlockHeight = 101
   505  	ctx, cleanUp := createTestCtxFromFile(
   506  		t, startingBlockHeight, basicGraphFilePath,
   507  	)
   508  	defer cleanUp()
   509  
   510  	// Get the channel ID.
   511  	roasbeefSongokuChanID := ctx.getChannelIDFromAlias(
   512  		t, "roasbeef", "songoku",
   513  	)
   514  	songokuSophonChanID := ctx.getChannelIDFromAlias(
   515  		t, "songoku", "sophon",
   516  	)
   517  
   518  	// Craft a LightningPayment struct that'll send a payment from roasbeef
   519  	// to sophon for 1000 atoms.
   520  	var payHash lntypes.Hash
   521  	amt := lnwire.NewMAtomsFromAtoms(1000)
   522  	payment := LightningPayment{
   523  		Target:      ctx.aliases["sophon"],
   524  		Amount:      amt,
   525  		FeeLimit:    noFeeLimit,
   526  		paymentHash: &payHash,
   527  	}
   528  
   529  	var preImage [32]byte
   530  	copy(preImage[:], bytes.Repeat([]byte{9}, 32))
   531  
   532  	// We'll also fetch the first outgoing channel edge from son goku
   533  	// to sophon. We'll obtain this as we'll need to to generate the
   534  	// FeeInsufficient error that we'll send back.
   535  	_, _, edgeUpdateToFail, err := ctx.graph.FetchChannelEdgesByID(
   536  		songokuSophonChanID,
   537  	)
   538  	require.NoError(t, err, "unable to fetch chan id")
   539  
   540  	errChanUpdate := lnwire.ChannelUpdate{
   541  		ShortChannelID: lnwire.NewShortChanIDFromInt(
   542  			songokuSophonChanID,
   543  		),
   544  		Timestamp:         uint32(edgeUpdateToFail.LastUpdate.Unix()),
   545  		MessageFlags:      edgeUpdateToFail.MessageFlags,
   546  		ChannelFlags:      edgeUpdateToFail.ChannelFlags,
   547  		TimeLockDelta:     edgeUpdateToFail.TimeLockDelta,
   548  		HtlcMinimumMAtoms: edgeUpdateToFail.MinHTLC,
   549  		HtlcMaximumMAtoms: edgeUpdateToFail.MaxHTLC,
   550  		BaseFee:           uint32(edgeUpdateToFail.FeeBaseMAtoms),
   551  		FeeRate:           uint32(edgeUpdateToFail.FeeProportionalMillionths),
   552  	}
   553  
   554  	signErrChanUpdate(t, ctx.privKeys["songoku"], &errChanUpdate)
   555  
   556  	// We'll now modify the SendToSwitch method to return an error for the
   557  	// outgoing channel to Son goku. This will be a fee related error, so
   558  	// it should only cause the edge to be pruned after the second attempt.
   559  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
   560  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
   561  
   562  			roasbeefSongoku := lnwire.NewShortChanIDFromInt(
   563  				roasbeefSongokuChanID,
   564  			)
   565  			if firstHop == roasbeefSongoku {
   566  				return [32]byte{}, htlcswitch.NewForwardingError(
   567  					// Within our error, we'll add a
   568  					// channel update which is meant to
   569  					// reflect the new fee schedule for the
   570  					// node/channel.
   571  					&lnwire.FailFeeInsufficient{
   572  						Update: errChanUpdate,
   573  					}, 1,
   574  				)
   575  			}
   576  
   577  			return preImage, nil
   578  		})
   579  
   580  	// Send off the payment request to the router, route through phamnuwen
   581  	// should've been selected as a fall back and succeeded correctly.
   582  	paymentPreImage, route, err := ctx.router.SendPayment(&payment)
   583  	require.NoError(t, err, "unable to send payment")
   584  
   585  	// The route selected should have two hops
   586  	require.Equal(t, 2, len(route.Hops), "incorrect route length")
   587  
   588  	// The preimage should match up with the once created above.
   589  	require.Equal(t, preImage[:], paymentPreImage[:], "incorrect preimage")
   590  
   591  	// The route should have pham nuwen as the first hop.
   592  	require.Equalf(t,
   593  		ctx.aliases["phamnuwen"], route.Hops[0].PubKeyBytes,
   594  		"route should go through pham nuwen as first hop, "+
   595  			"instead passes through: %v",
   596  		getAliasFromPubKey(route.Hops[0].PubKeyBytes, ctx.aliases),
   597  	)
   598  }
   599  
   600  // TestSendPaymentErrorFeeInsufficientPrivateEdge tests that if we receive
   601  // a fee related error from a private channel that we're attempting to route
   602  // through, then we'll update the fees in the route hints and successfully
   603  // route through the private channel in the second attempt.
   604  //
   605  // The test will send a payment from roasbeef to elst, available paths are,
   606  // path1: roasbeef -> songoku -> sophon -> elst, total fee: 210k
   607  // path2: roasbeef -> phamnuwen -> sophon -> elst, total fee: 220k
   608  // path3: roasbeef -> songoku ->(private channel) elst
   609  // We will setup the path3 to have the lowest fee so it's always the preferred
   610  // path.
   611  func TestSendPaymentErrorFeeInsufficientPrivateEdge(t *testing.T) {
   612  	t.Parallel()
   613  
   614  	const startingBlockHeight = 101
   615  	ctx, cleanUp := createTestCtxFromFile(
   616  		t, startingBlockHeight, basicGraphFilePath,
   617  	)
   618  	defer cleanUp()
   619  
   620  	// Get the channel ID.
   621  	roasbeefSongoku := lnwire.NewShortChanIDFromInt(
   622  		ctx.getChannelIDFromAlias(t, "roasbeef", "songoku"),
   623  	)
   624  
   625  	var (
   626  		payHash          lntypes.Hash
   627  		preImage         [32]byte
   628  		amt              = lnwire.NewMAtomsFromAtoms(1000)
   629  		privateChannelID = uint64(55555)
   630  		feeBaseMAtoms    = uint32(15)
   631  		expiryDelta      = uint16(32)
   632  		sgNode           = ctx.aliases["songoku"]
   633  	)
   634  
   635  	sgNodeID, err := secp256k1.ParsePubKey(sgNode[:])
   636  	require.NoError(t, err)
   637  
   638  	// Craft a LightningPayment struct that'll send a payment from roasbeef
   639  	// to elst, through a private channel between songoku and elst for
   640  	// 1000 satoshis. This route has lowest fees compared with the rest.
   641  	// This also holds when the private channel fee is updated to a higher
   642  	// value.
   643  	payment := LightningPayment{
   644  		Target:      ctx.aliases["elst"],
   645  		Amount:      amt,
   646  		FeeLimit:    noFeeLimit,
   647  		paymentHash: &payHash,
   648  		RouteHints: [][]zpay32.HopHint{{
   649  			// Add a private channel between songoku and elst.
   650  			zpay32.HopHint{
   651  				NodeID:          sgNodeID,
   652  				ChannelID:       privateChannelID,
   653  				FeeBaseMAtoms:   feeBaseMAtoms,
   654  				CLTVExpiryDelta: expiryDelta,
   655  			},
   656  		}},
   657  	}
   658  
   659  	// Prepare an error update for the private channel, with twice the
   660  	// original fee.
   661  	updatedFeeBaseMAtoms := feeBaseMAtoms * 2
   662  	errChanUpdate := lnwire.ChannelUpdate{
   663  		ShortChannelID: lnwire.NewShortChanIDFromInt(privateChannelID),
   664  		Timestamp:      uint32(testTime.Add(time.Minute).Unix()),
   665  		BaseFee:        updatedFeeBaseMAtoms,
   666  		TimeLockDelta:  expiryDelta,
   667  	}
   668  	signErrChanUpdate(t, ctx.privKeys["songoku"], &errChanUpdate)
   669  
   670  	// We'll now modify the SendHTLC method to return an error for the
   671  	// outgoing channel to songoku.
   672  	errorReturned := false
   673  	copy(preImage[:], bytes.Repeat([]byte{9}, 32))
   674  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
   675  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
   676  
   677  			if firstHop != roasbeefSongoku || errorReturned {
   678  				return preImage, nil
   679  			}
   680  
   681  			errorReturned = true
   682  			return [32]byte{}, htlcswitch.NewForwardingError(
   683  				// Within our error, we'll add a
   684  				// channel update which is meant to
   685  				// reflect the new fee schedule for the
   686  				// node/channel.
   687  				&lnwire.FailFeeInsufficient{
   688  					Update: errChanUpdate,
   689  				}, 1,
   690  			)
   691  		})
   692  
   693  	// Send off the payment request to the router, route through son
   694  	// goku and then across the private channel to elst.
   695  	paymentPreImage, route, err := ctx.router.SendPayment(&payment)
   696  	require.NoError(t, err, "unable to send payment")
   697  
   698  	require.True(t, errorReturned,
   699  		"failed to simulate error in the first payment attempt",
   700  	)
   701  
   702  	// The route selected should have two hops. Make sure that,
   703  	//   path: roasbeef -> son goku -> sophon -> elst
   704  	//   path: roasbeef -> pham nuwen -> sophon -> elst
   705  	// are not selected instead.
   706  	require.Equal(t, 2, len(route.Hops), "incorrect route length")
   707  
   708  	// The preimage should match up with the one created above.
   709  	require.Equal(t,
   710  		paymentPreImage[:], preImage[:], "incorrect preimage used",
   711  	)
   712  
   713  	// The route should have son goku as the first hop.
   714  	require.Equal(t, route.Hops[0].PubKeyBytes, ctx.aliases["songoku"],
   715  		"route should go through son goku as first hop",
   716  	)
   717  
   718  	// The route should pass via the private channel.
   719  	require.Equal(t,
   720  		privateChannelID, route.FinalHop().ChannelID,
   721  		"route did not pass through private channel "+
   722  			"between pham nuwen and elst",
   723  	)
   724  
   725  	// The route should have the updated fee.
   726  	require.Equal(t,
   727  		lnwire.MilliAtom(updatedFeeBaseMAtoms).String(),
   728  		route.HopFee(0).String(),
   729  		"fee to forward to the private channel not matched",
   730  	)
   731  }
   732  
   733  // TestSendPaymentPrivateEdgeUpdateFeeExceedsLimit tests that upon receiving a
   734  // ChannelUpdate in a fee related error from the private channel, we won't
   735  // choose the route in our second attempt if the updated fee exceeds our fee
   736  // limit specified in the payment.
   737  //
   738  // The test will send a payment from roasbeef to elst, available paths are,
   739  // path1: roasbeef -> songoku -> sophon -> elst, total fee: 210k
   740  // path2: roasbeef -> phamnuwen -> sophon -> elst, total fee: 220k
   741  // path3: roasbeef -> songoku ->(private channel) elst
   742  // We will setup the path3 to have the lowest fee and then update it with a fee
   743  // exceeds our fee limit, thus this route won't be chosen.
   744  func TestSendPaymentPrivateEdgeUpdateFeeExceedsLimit(t *testing.T) {
   745  	t.Parallel()
   746  
   747  	const startingBlockHeight = 101
   748  	ctx, cleanUp := createTestCtxFromFile(
   749  		t, startingBlockHeight, basicGraphFilePath,
   750  	)
   751  	defer cleanUp()
   752  
   753  	// Get the channel ID.
   754  	roasbeefSongoku := lnwire.NewShortChanIDFromInt(
   755  		ctx.getChannelIDFromAlias(t, "roasbeef", "songoku"),
   756  	)
   757  
   758  	var (
   759  		payHash          lntypes.Hash
   760  		preImage         [32]byte
   761  		amt              = lnwire.NewMAtomsFromAtoms(1000)
   762  		privateChannelID = uint64(55555)
   763  		feeBaseMSat      = uint32(15)
   764  		expiryDelta      = uint16(32)
   765  		sgNode           = ctx.aliases["songoku"]
   766  		feeLimit         = lnwire.MilliAtom(500000)
   767  	)
   768  
   769  	sgNodeID, err := secp256k1.ParsePubKey(sgNode[:])
   770  	require.NoError(t, err)
   771  
   772  	// Craft a LightningPayment struct that'll send a payment from roasbeef
   773  	// to elst, through a private channel between songoku and elst for
   774  	// 1000 satoshis. This route has lowest fees compared with the rest.
   775  	payment := LightningPayment{
   776  		Target:      ctx.aliases["elst"],
   777  		Amount:      amt,
   778  		FeeLimit:    feeLimit,
   779  		paymentHash: &payHash,
   780  		RouteHints: [][]zpay32.HopHint{{
   781  			// Add a private channel between songoku and elst.
   782  			zpay32.HopHint{
   783  				NodeID:          sgNodeID,
   784  				ChannelID:       privateChannelID,
   785  				FeeBaseMAtoms:   feeBaseMSat,
   786  				CLTVExpiryDelta: expiryDelta,
   787  			},
   788  		}},
   789  	}
   790  
   791  	// Prepare an error update for the private channel. The updated fee
   792  	// will exceeds the feeLimit.
   793  	updatedFeeBaseMAtoms := feeBaseMSat + uint32(feeLimit)
   794  	errChanUpdate := lnwire.ChannelUpdate{
   795  		ShortChannelID: lnwire.NewShortChanIDFromInt(privateChannelID),
   796  		Timestamp:      uint32(testTime.Add(time.Minute).Unix()),
   797  		BaseFee:        updatedFeeBaseMAtoms,
   798  		TimeLockDelta:  expiryDelta,
   799  	}
   800  	signErrChanUpdate(t, ctx.privKeys["songoku"], &errChanUpdate)
   801  
   802  	// We'll now modify the SendHTLC method to return an error for the
   803  	// outgoing channel to songoku.
   804  	errorReturned := false
   805  	copy(preImage[:], bytes.Repeat([]byte{9}, 32))
   806  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
   807  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
   808  
   809  			if firstHop != roasbeefSongoku || errorReturned {
   810  				return preImage, nil
   811  			}
   812  
   813  			errorReturned = true
   814  			return [32]byte{}, htlcswitch.NewForwardingError(
   815  				// Within our error, we'll add a
   816  				// channel update which is meant to
   817  				// reflect the new fee schedule for the
   818  				// node/channel.
   819  				&lnwire.FailFeeInsufficient{
   820  					Update: errChanUpdate,
   821  				}, 1,
   822  			)
   823  		})
   824  
   825  	// Send off the payment request to the router, route through son
   826  	// goku and then across the private channel to elst.
   827  	paymentPreImage, route, err := ctx.router.SendPayment(&payment)
   828  	require.NoError(t, err, "unable to send payment")
   829  
   830  	require.True(t, errorReturned,
   831  		"failed to simulate error in the first payment attempt",
   832  	)
   833  
   834  	// The route selected should have three hops. Make sure that,
   835  	//   path1: roasbeef -> son goku -> sophon -> elst
   836  	//   path2: roasbeef -> pham nuwen -> sophon -> elst
   837  	//   path3: roasbeef -> sophon -> (private channel) else
   838  	// path1 is selected.
   839  	require.Equal(t, 3, len(route.Hops), "incorrect route length")
   840  
   841  	// The preimage should match up with the one created above.
   842  	require.Equal(t,
   843  		paymentPreImage[:], preImage[:], "incorrect preimage used",
   844  	)
   845  
   846  	// The route should have son goku as the first hop.
   847  	require.Equal(t, route.Hops[0].PubKeyBytes, ctx.aliases["songoku"],
   848  		"route should go through son goku as the first hop",
   849  	)
   850  
   851  	// The route should have sophon as the first hop.
   852  	require.Equal(t, route.Hops[1].PubKeyBytes, ctx.aliases["sophon"],
   853  		"route should go through sophon as the second hop",
   854  	)
   855  	// The route should pass via the public channel.
   856  	require.Equal(t, route.FinalHop().PubKeyBytes, ctx.aliases["elst"],
   857  		"route should go through elst as the final hop",
   858  	)
   859  }
   860  
   861  // TestSendPaymentErrorNonFinalTimeLockErrors tests that if we receive either
   862  // an ExpiryTooSoon or a IncorrectCltvExpiry error from a node, then we prune
   863  // that node from the available graph witin a mission control session. This
   864  // test ensures that we'll route around errors due to nodes not knowing the
   865  // current block height.
   866  func TestSendPaymentErrorNonFinalTimeLockErrors(t *testing.T) {
   867  	t.Parallel()
   868  
   869  	const startingBlockHeight = 101
   870  	ctx, cleanUp := createTestCtxFromFile(
   871  		t, startingBlockHeight, basicGraphFilePath,
   872  	)
   873  	defer cleanUp()
   874  
   875  	// Craft a LightningPayment struct that'll send a payment from roasbeef
   876  	// to sophon for 1k atoms.
   877  	var payHash lntypes.Hash
   878  	amt := lnwire.NewMAtomsFromAtoms(1000)
   879  	payment := LightningPayment{
   880  		Target:      ctx.aliases["sophon"],
   881  		Amount:      amt,
   882  		FeeLimit:    noFeeLimit,
   883  		paymentHash: &payHash,
   884  	}
   885  
   886  	var preImage [32]byte
   887  	copy(preImage[:], bytes.Repeat([]byte{9}, 32))
   888  
   889  	// We'll also fetch the first outgoing channel edge from roasbeef to
   890  	// son goku. This edge will be included in the time lock related expiry
   891  	// errors that we'll get back due to disagrements in what the current
   892  	// block height is.
   893  	chanID := ctx.getChannelIDFromAlias(t, "roasbeef", "songoku")
   894  	roasbeefSongoku := lnwire.NewShortChanIDFromInt(chanID)
   895  
   896  	_, _, edgeUpdateToFail, err := ctx.graph.FetchChannelEdgesByID(chanID)
   897  	require.NoError(t, err, "unable to fetch chan id")
   898  
   899  	errChanUpdate := lnwire.ChannelUpdate{
   900  		ShortChannelID:    lnwire.NewShortChanIDFromInt(chanID),
   901  		Timestamp:         uint32(edgeUpdateToFail.LastUpdate.Unix()),
   902  		MessageFlags:      edgeUpdateToFail.MessageFlags,
   903  		ChannelFlags:      edgeUpdateToFail.ChannelFlags,
   904  		TimeLockDelta:     edgeUpdateToFail.TimeLockDelta,
   905  		HtlcMinimumMAtoms: edgeUpdateToFail.MinHTLC,
   906  		HtlcMaximumMAtoms: edgeUpdateToFail.MaxHTLC,
   907  		BaseFee:           uint32(edgeUpdateToFail.FeeBaseMAtoms),
   908  		FeeRate:           uint32(edgeUpdateToFail.FeeProportionalMillionths),
   909  	}
   910  
   911  	// We'll now modify the SendToSwitch method to return an error for the
   912  	// outgoing channel to son goku. Since this is a time lock related
   913  	// error, we should fail the payment flow all together, as Goku is the
   914  	// only channel to Sophon.
   915  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
   916  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
   917  
   918  			if firstHop == roasbeefSongoku {
   919  				return [32]byte{}, htlcswitch.NewForwardingError(
   920  					&lnwire.FailExpiryTooSoon{
   921  						Update: errChanUpdate,
   922  					}, 1,
   923  				)
   924  			}
   925  
   926  			return preImage, nil
   927  		})
   928  
   929  	// assertExpectedPath is a helper function that asserts the returned
   930  	// route properly routes around the failure we've introduced in the
   931  	// graph.
   932  	assertExpectedPath := func(retPreImage [32]byte, route *route.Route) {
   933  		// The route selected should have two hops
   934  		require.Equal(t, 2, len(route.Hops), "incorrect route length")
   935  
   936  		// The preimage should match up with the once created above.
   937  		require.Equal(t,
   938  			preImage[:], retPreImage[:], "incorrect preimage used",
   939  		)
   940  
   941  		// The route should have satoshi as the first hop.
   942  		require.Equalf(t,
   943  			ctx.aliases["phamnuwen"], route.Hops[0].PubKeyBytes,
   944  			"route should go through phamnuwen as first hop, "+
   945  				"instead passes through: %v",
   946  			getAliasFromPubKey(
   947  				route.Hops[0].PubKeyBytes, ctx.aliases,
   948  			),
   949  		)
   950  	}
   951  
   952  	// Send off the payment request to the router, this payment should
   953  	// succeed as we should actually go through Pham Nuwen in order to get
   954  	// to Sophon, even though he has higher fees.
   955  	paymentPreImage, rt, err := ctx.router.SendPayment(&payment)
   956  	require.NoError(t, err, "unable to send payment")
   957  
   958  	assertExpectedPath(paymentPreImage, rt)
   959  
   960  	// We'll now modify the error return an IncorrectCltvExpiry error
   961  	// instead, this should result in the same behavior of roasbeef routing
   962  	// around the faulty Son Goku node.
   963  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
   964  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
   965  
   966  			if firstHop == roasbeefSongoku {
   967  				return [32]byte{}, htlcswitch.NewForwardingError(
   968  					&lnwire.FailIncorrectCltvExpiry{
   969  						Update: errChanUpdate,
   970  					}, 1,
   971  				)
   972  			}
   973  
   974  			return preImage, nil
   975  		})
   976  
   977  	// Once again, Roasbeef should route around Goku since they disagree
   978  	// w.r.t to the block height, and instead go through Pham Nuwen. We
   979  	// flip a bit in the payment hash to allow resending this payment.
   980  	payment.paymentHash[1] ^= 1
   981  	paymentPreImage, rt, err = ctx.router.SendPayment(&payment)
   982  	require.NoError(t, err, "unable to send payment")
   983  
   984  	assertExpectedPath(paymentPreImage, rt)
   985  }
   986  
   987  // TestSendPaymentErrorPathPruning tests that the send of candidate routes
   988  // properly gets pruned in response to ForwardingError response from the
   989  // underlying SendToSwitch function.
   990  func TestSendPaymentErrorPathPruning(t *testing.T) {
   991  	t.Parallel()
   992  
   993  	const startingBlockHeight = 101
   994  	ctx, cleanUp := createTestCtxFromFile(
   995  		t, startingBlockHeight, basicGraphFilePath,
   996  	)
   997  	defer cleanUp()
   998  
   999  	// Craft a LightningPayment struct that'll send a payment from roasbeef
  1000  	// to luo ji for 1000 atoms, with a maximum of 1000 atoms in fees.
  1001  	var payHash lntypes.Hash
  1002  	paymentAmt := lnwire.NewMAtomsFromAtoms(1000)
  1003  	payment := LightningPayment{
  1004  		Target:      ctx.aliases["sophon"],
  1005  		Amount:      paymentAmt,
  1006  		FeeLimit:    noFeeLimit,
  1007  		paymentHash: &payHash,
  1008  	}
  1009  
  1010  	var preImage [32]byte
  1011  	copy(preImage[:], bytes.Repeat([]byte{9}, 32))
  1012  
  1013  	roasbeefSongoku := lnwire.NewShortChanIDFromInt(
  1014  		ctx.getChannelIDFromAlias(t, "roasbeef", "songoku"),
  1015  	)
  1016  	roasbeefPhanNuwen := lnwire.NewShortChanIDFromInt(
  1017  		ctx.getChannelIDFromAlias(t, "roasbeef", "phamnuwen"),
  1018  	)
  1019  
  1020  	// First, we'll modify the SendToSwitch method to return an error
  1021  	// indicating that the channel from roasbeef to son goku is not operable
  1022  	// with an UnknownNextPeer.
  1023  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
  1024  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
  1025  
  1026  			if firstHop == roasbeefSongoku {
  1027  				// We'll first simulate an error from the first
  1028  				// hop to simulate the channel from songoku to
  1029  				// sophon not having enough capacity.
  1030  				return [32]byte{}, htlcswitch.NewForwardingError(
  1031  					&lnwire.FailTemporaryChannelFailure{},
  1032  					1,
  1033  				)
  1034  			}
  1035  
  1036  			// Next, we'll create an error from phan nuwen to
  1037  			// indicate that the sophon node is not longer online,
  1038  			// which should prune out the rest of the routes.
  1039  			if firstHop == roasbeefPhanNuwen {
  1040  				return [32]byte{}, htlcswitch.NewForwardingError(
  1041  					&lnwire.FailUnknownNextPeer{}, 1,
  1042  				)
  1043  			}
  1044  
  1045  			return preImage, nil
  1046  		})
  1047  
  1048  	ctx.router.cfg.MissionControl.(*MissionControl).ResetHistory()
  1049  
  1050  	// When we try to dispatch that payment, we should receive an error as
  1051  	// both attempts should fail and cause both routes to be pruned.
  1052  	_, _, err := ctx.router.SendPayment(&payment)
  1053  	require.Error(t, err, "payment didn't return error")
  1054  
  1055  	// The final error returned should also indicate that the peer wasn't
  1056  	// online (the last error we returned).
  1057  	require.Equal(t, channeldb.FailureReasonNoRoute, err)
  1058  
  1059  	// Inspect the two attempts that were made before the payment failed.
  1060  	p, err := ctx.router.cfg.Control.FetchPayment(payHash)
  1061  	require.NoError(t, err)
  1062  
  1063  	require.Equal(t, 2, len(p.HTLCs), "expected two attempts")
  1064  
  1065  	// We expect the first attempt to have failed with a
  1066  	// TemporaryChannelFailure, the second with UnknownNextPeer.
  1067  	msg := p.HTLCs[0].Failure.Message
  1068  	_, ok := msg.(*lnwire.FailTemporaryChannelFailure)
  1069  	require.True(t, ok, "unexpected fail message")
  1070  
  1071  	msg = p.HTLCs[1].Failure.Message
  1072  	_, ok = msg.(*lnwire.FailUnknownNextPeer)
  1073  	require.True(t, ok, "unexpected fail message")
  1074  
  1075  	err = ctx.router.cfg.MissionControl.(*MissionControl).ResetHistory()
  1076  	require.NoError(t, err, "reset history failed")
  1077  
  1078  	// Next, we'll modify the SendToSwitch method to indicate that the
  1079  	// connection between songoku and isn't up.
  1080  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
  1081  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
  1082  
  1083  			if firstHop == roasbeefSongoku {
  1084  				failure := htlcswitch.NewForwardingError(
  1085  					&lnwire.FailUnknownNextPeer{}, 1,
  1086  				)
  1087  				return [32]byte{}, failure
  1088  			}
  1089  
  1090  			return preImage, nil
  1091  		})
  1092  
  1093  	// This shouldn't return an error, as we'll make a payment attempt via
  1094  	// the pham nuwen channel based on the assumption that there might be an
  1095  	// intermittent issue with the songoku <-> sophon channel.
  1096  	paymentPreImage, rt, err := ctx.router.SendPayment(&payment)
  1097  	require.NoError(t, err, "unable send payment")
  1098  
  1099  	// This path should go: roasbeef -> pham nuwen -> sophon
  1100  	require.Equal(t, 2, len(rt.Hops), "incorrect route length")
  1101  	require.Equal(t, preImage[:], paymentPreImage[:], "incorrect preimage")
  1102  	require.Equalf(t,
  1103  		ctx.aliases["phamnuwen"], rt.Hops[0].PubKeyBytes,
  1104  		"route should go through phamnuwen as first hop, "+
  1105  			"instead passes through: %v",
  1106  		getAliasFromPubKey(rt.Hops[0].PubKeyBytes, ctx.aliases),
  1107  	)
  1108  
  1109  	ctx.router.cfg.MissionControl.(*MissionControl).ResetHistory()
  1110  
  1111  	// Finally, we'll modify the SendToSwitch function to indicate that the
  1112  	// roasbeef -> luoji channel has insufficient capacity. This should
  1113  	// again cause us to instead go via the satoshi route.
  1114  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
  1115  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
  1116  
  1117  			if firstHop == roasbeefSongoku {
  1118  				// We'll first simulate an error from the first
  1119  				// outgoing link to simulate the channel from luo ji to
  1120  				// roasbeef not having enough capacity.
  1121  				return [32]byte{}, htlcswitch.NewForwardingError(
  1122  					&lnwire.FailTemporaryChannelFailure{},
  1123  					1,
  1124  				)
  1125  			}
  1126  			return preImage, nil
  1127  		})
  1128  
  1129  	// We flip a bit in the payment hash to allow resending this payment.
  1130  	payment.paymentHash[1] ^= 1
  1131  	paymentPreImage, rt, err = ctx.router.SendPayment(&payment)
  1132  	require.NoError(t, err, "unable send payment")
  1133  
  1134  	// This should succeed finally.  The route selected should have two
  1135  	// hops.
  1136  	require.Equal(t, 2, len(rt.Hops), "incorrect route length")
  1137  
  1138  	// The preimage should match up with the once created above.
  1139  	require.Equal(t, preImage[:], paymentPreImage[:], "incorrect preimage")
  1140  
  1141  	// The route should have satoshi as the first hop.
  1142  	require.Equalf(t,
  1143  		ctx.aliases["phamnuwen"], rt.Hops[0].PubKeyBytes,
  1144  		"route should go through phamnuwen as first hop, "+
  1145  			"instead passes through: %v",
  1146  		getAliasFromPubKey(rt.Hops[0].PubKeyBytes, ctx.aliases),
  1147  	)
  1148  }
  1149  
  1150  // TestAddProof checks that we can update the channel proof after channel
  1151  // info was added to the database.
  1152  func TestAddProof(t *testing.T) {
  1153  	t.Parallel()
  1154  
  1155  	ctx, cleanup := createTestCtxSingleNode(t, 0)
  1156  	defer cleanup()
  1157  
  1158  	// Before creating out edge, we'll create two new nodes within the
  1159  	// network that the channel will connect.
  1160  	node1, err := createTestNode()
  1161  	if err != nil {
  1162  		t.Fatal(err)
  1163  	}
  1164  	node2, err := createTestNode()
  1165  	if err != nil {
  1166  		t.Fatal(err)
  1167  	}
  1168  
  1169  	// In order to be able to add the edge we should have a valid funding
  1170  	// UTXO within the blockchain.
  1171  	fundingTx, _, chanID, err := createChannelEdge(ctx,
  1172  		bitcoinKey1.SerializeCompressed(), bitcoinKey2.SerializeCompressed(),
  1173  		100, 0)
  1174  	if err != nil {
  1175  		t.Fatalf("unable create channel edge: %v", err)
  1176  	}
  1177  	fundingBlock := &wire.MsgBlock{
  1178  		Transactions: []*wire.MsgTx{fundingTx},
  1179  	}
  1180  	ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight)
  1181  
  1182  	// After utxo was recreated adding the edge without the proof.
  1183  	edge := &channeldb.ChannelEdgeInfo{
  1184  		ChannelID:     chanID.ToUint64(),
  1185  		NodeKey1Bytes: node1.PubKeyBytes,
  1186  		NodeKey2Bytes: node2.PubKeyBytes,
  1187  		AuthProof:     nil,
  1188  	}
  1189  	copy(edge.DecredKey1Bytes[:], bitcoinKey1.SerializeCompressed())
  1190  	copy(edge.DecredKey2Bytes[:], bitcoinKey2.SerializeCompressed())
  1191  
  1192  	if err := ctx.router.AddEdge(edge); err != nil {
  1193  		t.Fatalf("unable to add edge: %v", err)
  1194  	}
  1195  
  1196  	// Now we'll attempt to update the proof and check that it has been
  1197  	// properly updated.
  1198  	if err := ctx.router.AddProof(*chanID, &testAuthProof); err != nil {
  1199  		t.Fatalf("unable to add proof: %v", err)
  1200  	}
  1201  
  1202  	info, _, _, err := ctx.router.GetChannelByID(*chanID)
  1203  	if err != nil {
  1204  		t.Fatalf("unable to get channel with id: %v", *chanID)
  1205  	}
  1206  	if info.AuthProof == nil {
  1207  		t.Fatal("proof have been updated")
  1208  	}
  1209  }
  1210  
  1211  // TestIgnoreNodeAnnouncement tests that adding a node to the router that is
  1212  // not known from any channel announcement, leads to the announcement being
  1213  // ignored.
  1214  func TestIgnoreNodeAnnouncement(t *testing.T) {
  1215  	t.Parallel()
  1216  
  1217  	const startingBlockHeight = 101
  1218  	ctx, cleanUp := createTestCtxFromFile(
  1219  		t, startingBlockHeight, basicGraphFilePath,
  1220  	)
  1221  	defer cleanUp()
  1222  
  1223  	pub := priv1.PubKey()
  1224  	node := &channeldb.LightningNode{
  1225  		HaveNodeAnnouncement: true,
  1226  		LastUpdate:           time.Unix(123, 0),
  1227  		Addresses:            testAddrs,
  1228  		Color:                color.RGBA{1, 2, 3, 0},
  1229  		Alias:                "node11",
  1230  		AuthSigBytes:         testSig.Serialize(),
  1231  		Features:             testFeatures,
  1232  	}
  1233  	copy(node.PubKeyBytes[:], pub.SerializeCompressed())
  1234  
  1235  	err := ctx.router.AddNode(node)
  1236  	if !IsError(err, ErrIgnored) {
  1237  		t.Fatalf("expected to get ErrIgnore, instead got: %v", err)
  1238  	}
  1239  }
  1240  
  1241  // TestIgnoreChannelEdgePolicyForUnknownChannel checks that a router will
  1242  // ignore a channel policy for a channel not in the graph.
  1243  func TestIgnoreChannelEdgePolicyForUnknownChannel(t *testing.T) {
  1244  	t.Parallel()
  1245  
  1246  	const startingBlockHeight = 101
  1247  
  1248  	// Setup an initially empty network.
  1249  	testChannels := []*testChannel{}
  1250  	testGraph, err := createTestGraphFromChannels(
  1251  		true, testChannels, "roasbeef",
  1252  	)
  1253  	if err != nil {
  1254  		t.Fatalf("unable to create graph: %v", err)
  1255  	}
  1256  	defer testGraph.cleanUp()
  1257  
  1258  	ctx, cleanUp := createTestCtxFromGraphInstance(
  1259  		t, startingBlockHeight, testGraph, false,
  1260  	)
  1261  	defer cleanUp()
  1262  
  1263  	var pub1 [33]byte
  1264  	copy(pub1[:], priv1.PubKey().SerializeCompressed())
  1265  
  1266  	var pub2 [33]byte
  1267  	copy(pub2[:], priv2.PubKey().SerializeCompressed())
  1268  
  1269  	// Add the edge between the two unknown nodes to the graph, and check
  1270  	// that the nodes are found after the fact.
  1271  	fundingTx, _, chanID, err := createChannelEdge(
  1272  		ctx, bitcoinKey1.SerializeCompressed(),
  1273  		bitcoinKey2.SerializeCompressed(), 10000, 500,
  1274  	)
  1275  	if err != nil {
  1276  		t.Fatalf("unable to create channel edge: %v", err)
  1277  	}
  1278  	fundingBlock := &wire.MsgBlock{
  1279  		Transactions: []*wire.MsgTx{fundingTx},
  1280  	}
  1281  	ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight)
  1282  
  1283  	edge := &channeldb.ChannelEdgeInfo{
  1284  		ChannelID:       chanID.ToUint64(),
  1285  		NodeKey1Bytes:   pub1,
  1286  		NodeKey2Bytes:   pub2,
  1287  		DecredKey1Bytes: pub1,
  1288  		DecredKey2Bytes: pub2,
  1289  		AuthProof:       nil,
  1290  	}
  1291  	edgePolicy := &channeldb.ChannelEdgePolicy{
  1292  		SigBytes:                  testSig.Serialize(),
  1293  		ChannelID:                 edge.ChannelID,
  1294  		LastUpdate:                testTime,
  1295  		TimeLockDelta:             10,
  1296  		MinHTLC:                   1,
  1297  		FeeBaseMAtoms:             10,
  1298  		FeeProportionalMillionths: 10000,
  1299  	}
  1300  
  1301  	// Attempt to update the edge. This should be ignored, since the edge
  1302  	// is not yet added to the router.
  1303  	err = ctx.router.UpdateEdge(edgePolicy)
  1304  	if !IsError(err, ErrIgnored) {
  1305  		t.Fatalf("expected to get ErrIgnore, instead got: %v", err)
  1306  	}
  1307  
  1308  	// Add the edge.
  1309  	if err := ctx.router.AddEdge(edge); err != nil {
  1310  		t.Fatalf("expected to be able to add edge to the channel graph,"+
  1311  			" even though the vertexes were unknown: %v.", err)
  1312  	}
  1313  
  1314  	// Now updating the edge policy should succeed.
  1315  	if err := ctx.router.UpdateEdge(edgePolicy); err != nil {
  1316  		t.Fatalf("unable to update edge policy: %v", err)
  1317  	}
  1318  }
  1319  
  1320  // TestAddEdgeUnknownVertexes tests that if an edge is added that contains two
  1321  // vertexes which we don't know of, the edge should be available for use
  1322  // regardless. This is due to the fact that we don't actually need node
  1323  // announcements for the channel vertexes to be able to use the channel.
  1324  func TestAddEdgeUnknownVertexes(t *testing.T) {
  1325  	t.Parallel()
  1326  
  1327  	const startingBlockHeight = 101
  1328  	ctx, cleanUp := createTestCtxFromFile(
  1329  		t, startingBlockHeight, basicGraphFilePath,
  1330  	)
  1331  	defer cleanUp()
  1332  
  1333  	var pub1 [33]byte
  1334  	copy(pub1[:], priv1.PubKey().SerializeCompressed())
  1335  
  1336  	var pub2 [33]byte
  1337  	copy(pub2[:], priv2.PubKey().SerializeCompressed())
  1338  
  1339  	// The two nodes we are about to add should not exist yet.
  1340  	_, exists1, err := ctx.graph.HasLightningNode(pub1)
  1341  	if err != nil {
  1342  		t.Fatalf("unable to query graph: %v", err)
  1343  	}
  1344  	if exists1 {
  1345  		t.Fatalf("node already existed")
  1346  	}
  1347  	_, exists2, err := ctx.graph.HasLightningNode(pub2)
  1348  	if err != nil {
  1349  		t.Fatalf("unable to query graph: %v", err)
  1350  	}
  1351  	if exists2 {
  1352  		t.Fatalf("node already existed")
  1353  	}
  1354  
  1355  	// Add the edge between the two unknown nodes to the graph, and check
  1356  	// that the nodes are found after the fact.
  1357  	fundingTx, _, chanID, err := createChannelEdge(ctx,
  1358  		bitcoinKey1.SerializeCompressed(),
  1359  		bitcoinKey2.SerializeCompressed(),
  1360  		10000, 500,
  1361  	)
  1362  	if err != nil {
  1363  		t.Fatalf("unable to create channel edge: %v", err)
  1364  	}
  1365  	fundingBlock := &wire.MsgBlock{
  1366  		Transactions: []*wire.MsgTx{fundingTx},
  1367  	}
  1368  	ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight)
  1369  
  1370  	edge := &channeldb.ChannelEdgeInfo{
  1371  		ChannelID:       chanID.ToUint64(),
  1372  		NodeKey1Bytes:   pub1,
  1373  		NodeKey2Bytes:   pub2,
  1374  		DecredKey1Bytes: pub1,
  1375  		DecredKey2Bytes: pub2,
  1376  		AuthProof:       nil,
  1377  	}
  1378  	if err := ctx.router.AddEdge(edge); err != nil {
  1379  		t.Fatalf("expected to be able to add edge to the channel graph,"+
  1380  			" even though the vertexes were unknown: %v.", err)
  1381  	}
  1382  
  1383  	// We must add the edge policy to be able to use the edge for route
  1384  	// finding.
  1385  	edgePolicy := &channeldb.ChannelEdgePolicy{
  1386  		SigBytes:                  testSig.Serialize(),
  1387  		ChannelID:                 edge.ChannelID,
  1388  		LastUpdate:                testTime,
  1389  		TimeLockDelta:             10,
  1390  		MinHTLC:                   1,
  1391  		FeeBaseMAtoms:             10,
  1392  		FeeProportionalMillionths: 10000,
  1393  		Node: &channeldb.LightningNode{
  1394  			PubKeyBytes: edge.NodeKey2Bytes,
  1395  		},
  1396  	}
  1397  	edgePolicy.ChannelFlags = 0
  1398  
  1399  	if err := ctx.router.UpdateEdge(edgePolicy); err != nil {
  1400  		t.Fatalf("unable to update edge policy: %v", err)
  1401  	}
  1402  
  1403  	// Create edge in the other direction as well.
  1404  	edgePolicy = &channeldb.ChannelEdgePolicy{
  1405  		SigBytes:                  testSig.Serialize(),
  1406  		ChannelID:                 edge.ChannelID,
  1407  		LastUpdate:                testTime,
  1408  		TimeLockDelta:             10,
  1409  		MinHTLC:                   1,
  1410  		FeeBaseMAtoms:             10,
  1411  		FeeProportionalMillionths: 10000,
  1412  		Node: &channeldb.LightningNode{
  1413  			PubKeyBytes: edge.NodeKey1Bytes,
  1414  		},
  1415  	}
  1416  	edgePolicy.ChannelFlags = 1
  1417  
  1418  	if err := ctx.router.UpdateEdge(edgePolicy); err != nil {
  1419  		t.Fatalf("unable to update edge policy: %v", err)
  1420  	}
  1421  
  1422  	// After adding the edge between the two previously unknown nodes, they
  1423  	// should have been added to the graph.
  1424  	_, exists1, err = ctx.graph.HasLightningNode(pub1)
  1425  	if err != nil {
  1426  		t.Fatalf("unable to query graph: %v", err)
  1427  	}
  1428  	if !exists1 {
  1429  		t.Fatalf("node1 was not added to the graph")
  1430  	}
  1431  	_, exists2, err = ctx.graph.HasLightningNode(pub2)
  1432  	if err != nil {
  1433  		t.Fatalf("unable to query graph: %v", err)
  1434  	}
  1435  	if !exists2 {
  1436  		t.Fatalf("node2 was not added to the graph")
  1437  	}
  1438  
  1439  	// We will connect node1 to the rest of the test graph, and make sure
  1440  	// we can find a route to node2, which will use the just added channel
  1441  	// edge.
  1442  
  1443  	// We will connect node 1 to "sophon"
  1444  	connectNode := ctx.aliases["sophon"]
  1445  	connectNodeKey, err := secp256k1.ParsePubKey(connectNode[:])
  1446  	if err != nil {
  1447  		t.Fatal(err)
  1448  	}
  1449  
  1450  	var (
  1451  		pubKey1 *secp256k1.PublicKey
  1452  		pubKey2 *secp256k1.PublicKey
  1453  	)
  1454  	node1Bytes := priv1.PubKey().SerializeCompressed()
  1455  	node2Bytes := connectNode
  1456  	if bytes.Compare(node1Bytes[:], node2Bytes[:]) == -1 {
  1457  		pubKey1 = priv1.PubKey()
  1458  		pubKey2 = connectNodeKey
  1459  	} else {
  1460  		pubKey1 = connectNodeKey
  1461  		pubKey2 = priv1.PubKey()
  1462  	}
  1463  
  1464  	fundingTx, _, chanID, err = createChannelEdge(ctx,
  1465  		pubKey1.SerializeCompressed(), pubKey2.SerializeCompressed(),
  1466  		10000, 510)
  1467  	if err != nil {
  1468  		t.Fatalf("unable to create channel edge: %v", err)
  1469  	}
  1470  	fundingBlock = &wire.MsgBlock{
  1471  		Transactions: []*wire.MsgTx{fundingTx},
  1472  	}
  1473  	ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight)
  1474  
  1475  	edge = &channeldb.ChannelEdgeInfo{
  1476  		ChannelID: chanID.ToUint64(),
  1477  		AuthProof: nil,
  1478  	}
  1479  	copy(edge.NodeKey1Bytes[:], node1Bytes)
  1480  	edge.NodeKey2Bytes = node2Bytes
  1481  	copy(edge.DecredKey1Bytes[:], node1Bytes)
  1482  	edge.DecredKey2Bytes = node2Bytes
  1483  
  1484  	if err := ctx.router.AddEdge(edge); err != nil {
  1485  		t.Fatalf("unable to add edge to the channel graph: %v.", err)
  1486  	}
  1487  
  1488  	edgePolicy = &channeldb.ChannelEdgePolicy{
  1489  		SigBytes:                  testSig.Serialize(),
  1490  		ChannelID:                 edge.ChannelID,
  1491  		LastUpdate:                testTime,
  1492  		TimeLockDelta:             10,
  1493  		MinHTLC:                   1,
  1494  		FeeBaseMAtoms:             10,
  1495  		FeeProportionalMillionths: 10000,
  1496  		Node: &channeldb.LightningNode{
  1497  			PubKeyBytes: edge.NodeKey2Bytes,
  1498  		},
  1499  	}
  1500  	edgePolicy.ChannelFlags = 0
  1501  
  1502  	if err := ctx.router.UpdateEdge(edgePolicy); err != nil {
  1503  		t.Fatalf("unable to update edge policy: %v", err)
  1504  	}
  1505  
  1506  	edgePolicy = &channeldb.ChannelEdgePolicy{
  1507  		SigBytes:                  testSig.Serialize(),
  1508  		ChannelID:                 edge.ChannelID,
  1509  		LastUpdate:                testTime,
  1510  		TimeLockDelta:             10,
  1511  		MinHTLC:                   1,
  1512  		FeeBaseMAtoms:             10,
  1513  		FeeProportionalMillionths: 10000,
  1514  		Node: &channeldb.LightningNode{
  1515  			PubKeyBytes: edge.NodeKey1Bytes,
  1516  		},
  1517  	}
  1518  	edgePolicy.ChannelFlags = 1
  1519  
  1520  	if err := ctx.router.UpdateEdge(edgePolicy); err != nil {
  1521  		t.Fatalf("unable to update edge policy: %v", err)
  1522  	}
  1523  
  1524  	// We should now be able to find a route to node 2.
  1525  	paymentAmt := lnwire.NewMAtomsFromAtoms(100)
  1526  	targetNode := priv2.PubKey()
  1527  	var targetPubKeyBytes route.Vertex
  1528  	copy(targetPubKeyBytes[:], targetNode.SerializeCompressed())
  1529  	_, err = ctx.router.FindRoute(
  1530  		ctx.router.selfNode.PubKeyBytes,
  1531  		targetPubKeyBytes, paymentAmt, noRestrictions, nil, nil,
  1532  		MinCLTVDelta,
  1533  	)
  1534  	if err != nil {
  1535  		t.Fatalf("unable to find any routes: %v", err)
  1536  	}
  1537  
  1538  	// Now check that we can update the node info for the partial node
  1539  	// without messing up the channel graph.
  1540  	n1 := &channeldb.LightningNode{
  1541  		HaveNodeAnnouncement: true,
  1542  		LastUpdate:           time.Unix(123, 0),
  1543  		Addresses:            testAddrs,
  1544  		Color:                color.RGBA{1, 2, 3, 0},
  1545  		Alias:                "node11",
  1546  		AuthSigBytes:         testSig.Serialize(),
  1547  		Features:             testFeatures,
  1548  	}
  1549  	copy(n1.PubKeyBytes[:], priv1.PubKey().SerializeCompressed())
  1550  
  1551  	if err := ctx.router.AddNode(n1); err != nil {
  1552  		t.Fatalf("could not add node: %v", err)
  1553  	}
  1554  
  1555  	n2 := &channeldb.LightningNode{
  1556  		HaveNodeAnnouncement: true,
  1557  		LastUpdate:           time.Unix(123, 0),
  1558  		Addresses:            testAddrs,
  1559  		Color:                color.RGBA{1, 2, 3, 0},
  1560  		Alias:                "node22",
  1561  		AuthSigBytes:         testSig.Serialize(),
  1562  		Features:             testFeatures,
  1563  	}
  1564  	copy(n2.PubKeyBytes[:], priv2.PubKey().SerializeCompressed())
  1565  
  1566  	if err := ctx.router.AddNode(n2); err != nil {
  1567  		t.Fatalf("could not add node: %v", err)
  1568  	}
  1569  
  1570  	// Should still be able to find the route, and the info should be
  1571  	// updated.
  1572  	_, err = ctx.router.FindRoute(
  1573  		ctx.router.selfNode.PubKeyBytes,
  1574  		targetPubKeyBytes, paymentAmt, noRestrictions, nil, nil,
  1575  		MinCLTVDelta,
  1576  	)
  1577  	if err != nil {
  1578  		t.Fatalf("unable to find any routes: %v", err)
  1579  	}
  1580  
  1581  	copy1, err := ctx.graph.FetchLightningNode(pub1)
  1582  	if err != nil {
  1583  		t.Fatalf("unable to fetch node: %v", err)
  1584  	}
  1585  
  1586  	if copy1.Alias != n1.Alias {
  1587  		t.Fatalf("fetched node not equal to original")
  1588  	}
  1589  
  1590  	copy2, err := ctx.graph.FetchLightningNode(pub2)
  1591  	if err != nil {
  1592  		t.Fatalf("unable to fetch node: %v", err)
  1593  	}
  1594  
  1595  	if copy2.Alias != n2.Alias {
  1596  		t.Fatalf("fetched node not equal to original")
  1597  	}
  1598  }
  1599  
  1600  // TestWakeUpOnStaleBranch tests that upon startup of the ChannelRouter, if the
  1601  // the chain previously reflected in the channel graph is stale (overtaken by a
  1602  // longer chain), the channel router will prune the graph for any channels
  1603  // confirmed on the stale chain, and resync to the main chain.
  1604  func TestWakeUpOnStaleBranch(t *testing.T) {
  1605  	t.Parallel()
  1606  
  1607  	const startingBlockHeight = 101
  1608  	ctx, cleanUp := createTestCtxSingleNode(t, startingBlockHeight)
  1609  	defer cleanUp()
  1610  
  1611  	const chanValue = 10000
  1612  
  1613  	// chanID1 will not be reorged out.
  1614  	var chanID1 uint64
  1615  
  1616  	// chanID2 will be reorged out.
  1617  	var chanID2 uint64
  1618  
  1619  	// Create 10 common blocks, confirming chanID1.
  1620  	for i := uint32(1); i <= 10; i++ {
  1621  		block := &wire.MsgBlock{
  1622  			Transactions: []*wire.MsgTx{},
  1623  		}
  1624  		height := startingBlockHeight + i
  1625  		if i == 5 {
  1626  			fundingTx, _, chanID, err := createChannelEdge(ctx,
  1627  				bitcoinKey1.SerializeCompressed(),
  1628  				bitcoinKey2.SerializeCompressed(),
  1629  				chanValue, height)
  1630  			if err != nil {
  1631  				t.Fatalf("unable create channel edge: %v", err)
  1632  			}
  1633  			block.Transactions = append(block.Transactions,
  1634  				fundingTx)
  1635  			chanID1 = chanID.ToUint64()
  1636  
  1637  		}
  1638  		ctx.chain.addBlock(block, height, rand.Uint32())
  1639  		ctx.chain.setBestBlock(int32(height))
  1640  		ctx.chainView.notifyBlock(block.BlockHash(), height,
  1641  			[]*wire.MsgTx{}, t)
  1642  	}
  1643  
  1644  	// Give time to process new blocks
  1645  	time.Sleep(time.Millisecond * 500)
  1646  
  1647  	_, forkHeight, err := ctx.chain.GetBestBlock()
  1648  	if err != nil {
  1649  		t.Fatalf("unable to ge best block: %v", err)
  1650  	}
  1651  
  1652  	// Create 10 blocks on the minority chain, confirming chanID2.
  1653  	for i := uint32(1); i <= 10; i++ {
  1654  		block := &wire.MsgBlock{
  1655  			Transactions: []*wire.MsgTx{},
  1656  		}
  1657  		height := uint32(forkHeight) + i
  1658  		if i == 5 {
  1659  			fundingTx, _, chanID, err := createChannelEdge(ctx,
  1660  				bitcoinKey1.SerializeCompressed(),
  1661  				bitcoinKey2.SerializeCompressed(),
  1662  				chanValue, height)
  1663  			if err != nil {
  1664  				t.Fatalf("unable create channel edge: %v", err)
  1665  			}
  1666  			block.Transactions = append(block.Transactions,
  1667  				fundingTx)
  1668  			chanID2 = chanID.ToUint64()
  1669  		}
  1670  		ctx.chain.addBlock(block, height, rand.Uint32())
  1671  		ctx.chain.setBestBlock(int32(height))
  1672  		ctx.chainView.notifyBlock(block.BlockHash(), height,
  1673  			[]*wire.MsgTx{}, t)
  1674  	}
  1675  	// Give time to process new blocks
  1676  	time.Sleep(time.Millisecond * 500)
  1677  
  1678  	// Now add the two edges to the channel graph, and check that they
  1679  	// correctly show up in the database.
  1680  	node1, err := createTestNode()
  1681  	if err != nil {
  1682  		t.Fatalf("unable to create test node: %v", err)
  1683  	}
  1684  	node2, err := createTestNode()
  1685  	if err != nil {
  1686  		t.Fatalf("unable to create test node: %v", err)
  1687  	}
  1688  
  1689  	edge1 := &channeldb.ChannelEdgeInfo{
  1690  		ChannelID:     chanID1,
  1691  		NodeKey1Bytes: node1.PubKeyBytes,
  1692  		NodeKey2Bytes: node2.PubKeyBytes,
  1693  		AuthProof: &channeldb.ChannelAuthProof{
  1694  			NodeSig1Bytes:   testSig.Serialize(),
  1695  			NodeSig2Bytes:   testSig.Serialize(),
  1696  			DecredSig1Bytes: testSig.Serialize(),
  1697  			DecredSig2Bytes: testSig.Serialize(),
  1698  		},
  1699  	}
  1700  	copy(edge1.DecredKey1Bytes[:], bitcoinKey1.SerializeCompressed())
  1701  	copy(edge1.DecredKey2Bytes[:], bitcoinKey2.SerializeCompressed())
  1702  
  1703  	if err := ctx.router.AddEdge(edge1); err != nil {
  1704  		t.Fatalf("unable to add edge: %v", err)
  1705  	}
  1706  
  1707  	edge2 := &channeldb.ChannelEdgeInfo{
  1708  		ChannelID:     chanID2,
  1709  		NodeKey1Bytes: node1.PubKeyBytes,
  1710  		NodeKey2Bytes: node2.PubKeyBytes,
  1711  		AuthProof: &channeldb.ChannelAuthProof{
  1712  			NodeSig1Bytes:   testSig.Serialize(),
  1713  			NodeSig2Bytes:   testSig.Serialize(),
  1714  			DecredSig1Bytes: testSig.Serialize(),
  1715  			DecredSig2Bytes: testSig.Serialize(),
  1716  		},
  1717  	}
  1718  	copy(edge2.DecredKey1Bytes[:], bitcoinKey1.SerializeCompressed())
  1719  	copy(edge2.DecredKey2Bytes[:], bitcoinKey2.SerializeCompressed())
  1720  
  1721  	if err := ctx.router.AddEdge(edge2); err != nil {
  1722  		t.Fatalf("unable to add edge: %v", err)
  1723  	}
  1724  
  1725  	// Check that the fundingTxs are in the graph db.
  1726  	_, _, has, isZombie, err := ctx.graph.HasChannelEdge(chanID1)
  1727  	if err != nil {
  1728  		t.Fatalf("error looking for edge: %v", chanID1)
  1729  	}
  1730  	if !has {
  1731  		t.Fatalf("could not find edge in graph")
  1732  	}
  1733  	if isZombie {
  1734  		t.Fatal("edge was marked as zombie")
  1735  	}
  1736  
  1737  	_, _, has, isZombie, err = ctx.graph.HasChannelEdge(chanID2)
  1738  	if err != nil {
  1739  		t.Fatalf("error looking for edge: %v", chanID2)
  1740  	}
  1741  	if !has {
  1742  		t.Fatalf("could not find edge in graph")
  1743  	}
  1744  	if isZombie {
  1745  		t.Fatal("edge was marked as zombie")
  1746  	}
  1747  
  1748  	// Stop the router, so we can reorg the chain while its offline.
  1749  	if err := ctx.router.Stop(); err != nil {
  1750  		t.Fatalf("unable to stop router: %v", err)
  1751  	}
  1752  
  1753  	// Create a 15 block fork.
  1754  	for i := uint32(1); i <= 15; i++ {
  1755  		block := &wire.MsgBlock{
  1756  			Transactions: []*wire.MsgTx{},
  1757  		}
  1758  		height := uint32(forkHeight) + i
  1759  		ctx.chain.addBlock(block, height, rand.Uint32())
  1760  		ctx.chain.setBestBlock(int32(height))
  1761  	}
  1762  
  1763  	// Give time to process new blocks.
  1764  	time.Sleep(time.Millisecond * 500)
  1765  
  1766  	// Create new router with same graph database.
  1767  	router, err := New(Config{
  1768  		Graph:              ctx.graph,
  1769  		Chain:              ctx.chain,
  1770  		ChainView:          ctx.chainView,
  1771  		Payer:              &mockPaymentAttemptDispatcherOld{},
  1772  		Control:            makeMockControlTower(),
  1773  		ChannelPruneExpiry: time.Hour * 24,
  1774  		GraphPruneInterval: time.Hour * 2,
  1775  
  1776  		// We'll set the delay to zero to prune immediately.
  1777  		FirstTimePruneDelay: 0,
  1778  	})
  1779  	if err != nil {
  1780  		t.Fatalf("unable to create router %v", err)
  1781  	}
  1782  
  1783  	// It should resync to the longer chain on startup.
  1784  	if err := router.Start(); err != nil {
  1785  		t.Fatalf("unable to start router: %v", err)
  1786  	}
  1787  
  1788  	// The channel with chanID2 should not be in the database anymore,
  1789  	// since it is not confirmed on the longest chain. chanID1 should
  1790  	// still be.
  1791  	_, _, has, isZombie, err = ctx.graph.HasChannelEdge(chanID1)
  1792  	if err != nil {
  1793  		t.Fatalf("error looking for edge: %v", chanID1)
  1794  	}
  1795  	if !has {
  1796  		t.Fatalf("did not find edge in graph")
  1797  	}
  1798  	if isZombie {
  1799  		t.Fatal("edge was marked as zombie")
  1800  	}
  1801  
  1802  	_, _, has, isZombie, err = ctx.graph.HasChannelEdge(chanID2)
  1803  	if err != nil {
  1804  		t.Fatalf("error looking for edge: %v", chanID2)
  1805  	}
  1806  	if has {
  1807  		t.Fatalf("found edge in graph")
  1808  	}
  1809  	if isZombie {
  1810  		t.Fatal("reorged edge should not be marked as zombie")
  1811  	}
  1812  }
  1813  
  1814  // TestDisconnectedBlocks checks that the router handles a reorg happening when
  1815  // it is active.
  1816  func TestDisconnectedBlocks(t *testing.T) {
  1817  	t.Parallel()
  1818  
  1819  	const startingBlockHeight = 101
  1820  	ctx, cleanUp := createTestCtxSingleNode(t, startingBlockHeight)
  1821  	defer cleanUp()
  1822  
  1823  	const chanValue = 10000
  1824  
  1825  	// chanID1 will not be reorged out, while chanID2 will be reorged out.
  1826  	var chanID1, chanID2 uint64
  1827  
  1828  	// Create 10 common blocks, confirming chanID1.
  1829  	for i := uint32(1); i <= 10; i++ {
  1830  		block := &wire.MsgBlock{
  1831  			Transactions: []*wire.MsgTx{},
  1832  		}
  1833  		height := startingBlockHeight + i
  1834  		if i == 5 {
  1835  			fundingTx, _, chanID, err := createChannelEdge(ctx,
  1836  				bitcoinKey1.SerializeCompressed(),
  1837  				bitcoinKey2.SerializeCompressed(),
  1838  				chanValue, height)
  1839  			if err != nil {
  1840  				t.Fatalf("unable create channel edge: %v", err)
  1841  			}
  1842  			block.Transactions = append(block.Transactions,
  1843  				fundingTx)
  1844  			chanID1 = chanID.ToUint64()
  1845  
  1846  		}
  1847  		ctx.chain.addBlock(block, height, rand.Uint32())
  1848  		ctx.chain.setBestBlock(int32(height))
  1849  		ctx.chainView.notifyBlock(block.BlockHash(), height,
  1850  			[]*wire.MsgTx{}, t)
  1851  	}
  1852  
  1853  	// Give time to process new blocks
  1854  	time.Sleep(time.Millisecond * 500)
  1855  
  1856  	_, forkHeight, err := ctx.chain.GetBestBlock()
  1857  	if err != nil {
  1858  		t.Fatalf("unable to get best block: %v", err)
  1859  	}
  1860  
  1861  	// Create 10 blocks on the minority chain, confirming chanID2.
  1862  	var minorityChain []*wire.MsgBlock
  1863  	for i := uint32(1); i <= 10; i++ {
  1864  		block := &wire.MsgBlock{
  1865  			Transactions: []*wire.MsgTx{},
  1866  		}
  1867  		height := uint32(forkHeight) + i
  1868  		if i == 5 {
  1869  			fundingTx, _, chanID, err := createChannelEdge(ctx,
  1870  				bitcoinKey1.SerializeCompressed(),
  1871  				bitcoinKey2.SerializeCompressed(),
  1872  				chanValue, height)
  1873  			if err != nil {
  1874  				t.Fatalf("unable create channel edge: %v", err)
  1875  			}
  1876  			block.Transactions = append(block.Transactions,
  1877  				fundingTx)
  1878  			chanID2 = chanID.ToUint64()
  1879  		}
  1880  		minorityChain = append(minorityChain, block)
  1881  		ctx.chain.addBlock(block, height, rand.Uint32())
  1882  		ctx.chain.setBestBlock(int32(height))
  1883  		ctx.chainView.notifyBlock(block.BlockHash(), height,
  1884  			[]*wire.MsgTx{}, t)
  1885  	}
  1886  	// Give time to process new blocks
  1887  	time.Sleep(time.Millisecond * 500)
  1888  
  1889  	// Now add the two edges to the channel graph, and check that they
  1890  	// correctly show up in the database.
  1891  	node1, err := createTestNode()
  1892  	if err != nil {
  1893  		t.Fatalf("unable to create test node: %v", err)
  1894  	}
  1895  	node2, err := createTestNode()
  1896  	if err != nil {
  1897  		t.Fatalf("unable to create test node: %v", err)
  1898  	}
  1899  
  1900  	edge1 := &channeldb.ChannelEdgeInfo{
  1901  		ChannelID:       chanID1,
  1902  		NodeKey1Bytes:   node1.PubKeyBytes,
  1903  		NodeKey2Bytes:   node2.PubKeyBytes,
  1904  		DecredKey1Bytes: node1.PubKeyBytes,
  1905  		DecredKey2Bytes: node2.PubKeyBytes,
  1906  		AuthProof: &channeldb.ChannelAuthProof{
  1907  			NodeSig1Bytes:   testSig.Serialize(),
  1908  			NodeSig2Bytes:   testSig.Serialize(),
  1909  			DecredSig1Bytes: testSig.Serialize(),
  1910  			DecredSig2Bytes: testSig.Serialize(),
  1911  		},
  1912  	}
  1913  	copy(edge1.DecredKey1Bytes[:], bitcoinKey1.SerializeCompressed())
  1914  	copy(edge1.DecredKey2Bytes[:], bitcoinKey2.SerializeCompressed())
  1915  
  1916  	if err := ctx.router.AddEdge(edge1); err != nil {
  1917  		t.Fatalf("unable to add edge: %v", err)
  1918  	}
  1919  
  1920  	edge2 := &channeldb.ChannelEdgeInfo{
  1921  		ChannelID:       chanID2,
  1922  		NodeKey1Bytes:   node1.PubKeyBytes,
  1923  		NodeKey2Bytes:   node2.PubKeyBytes,
  1924  		DecredKey1Bytes: node1.PubKeyBytes,
  1925  		DecredKey2Bytes: node2.PubKeyBytes,
  1926  		AuthProof: &channeldb.ChannelAuthProof{
  1927  			NodeSig1Bytes:   testSig.Serialize(),
  1928  			NodeSig2Bytes:   testSig.Serialize(),
  1929  			DecredSig1Bytes: testSig.Serialize(),
  1930  			DecredSig2Bytes: testSig.Serialize(),
  1931  		},
  1932  	}
  1933  	copy(edge2.DecredKey1Bytes[:], bitcoinKey1.SerializeCompressed())
  1934  	copy(edge2.DecredKey2Bytes[:], bitcoinKey2.SerializeCompressed())
  1935  
  1936  	if err := ctx.router.AddEdge(edge2); err != nil {
  1937  		t.Fatalf("unable to add edge: %v", err)
  1938  	}
  1939  
  1940  	// Check that the fundingTxs are in the graph db.
  1941  	_, _, has, isZombie, err := ctx.graph.HasChannelEdge(chanID1)
  1942  	if err != nil {
  1943  		t.Fatalf("error looking for edge: %v", chanID1)
  1944  	}
  1945  	if !has {
  1946  		t.Fatalf("could not find edge in graph")
  1947  	}
  1948  	if isZombie {
  1949  		t.Fatal("edge was marked as zombie")
  1950  	}
  1951  
  1952  	_, _, has, isZombie, err = ctx.graph.HasChannelEdge(chanID2)
  1953  	if err != nil {
  1954  		t.Fatalf("error looking for edge: %v", chanID2)
  1955  	}
  1956  	if !has {
  1957  		t.Fatalf("could not find edge in graph")
  1958  	}
  1959  	if isZombie {
  1960  		t.Fatal("edge was marked as zombie")
  1961  	}
  1962  
  1963  	// Create a 15 block fork. We first let the chainView notify the router
  1964  	// about stale blocks, before sending the now connected blocks. We do
  1965  	// this because we expect this order from the chainview.
  1966  	ctx.chainView.notifyStaleBlockAck = make(chan struct{}, 1)
  1967  	for i := len(minorityChain) - 1; i >= 0; i-- {
  1968  		block := minorityChain[i]
  1969  		height := uint32(forkHeight) + uint32(i) + 1
  1970  		ctx.chainView.notifyStaleBlock(block.BlockHash(), height,
  1971  			block.Transactions, t)
  1972  		<-ctx.chainView.notifyStaleBlockAck
  1973  	}
  1974  
  1975  	time.Sleep(time.Second * 2)
  1976  
  1977  	ctx.chainView.notifyBlockAck = make(chan struct{}, 1)
  1978  	for i := uint32(1); i <= 15; i++ {
  1979  		block := &wire.MsgBlock{
  1980  			Transactions: []*wire.MsgTx{},
  1981  		}
  1982  		height := uint32(forkHeight) + i
  1983  		ctx.chain.addBlock(block, height, rand.Uint32())
  1984  		ctx.chain.setBestBlock(int32(height))
  1985  		ctx.chainView.notifyBlock(block.BlockHash(), height,
  1986  			block.Transactions, t)
  1987  		<-ctx.chainView.notifyBlockAck
  1988  	}
  1989  
  1990  	time.Sleep(time.Millisecond * 500)
  1991  
  1992  	// chanID2 should not be in the database anymore, since it is not
  1993  	// confirmed on the longest chain. chanID1 should still be.
  1994  	_, _, has, isZombie, err = ctx.graph.HasChannelEdge(chanID1)
  1995  	if err != nil {
  1996  		t.Fatalf("error looking for edge: %v", chanID1)
  1997  	}
  1998  	if !has {
  1999  		t.Fatalf("did not find edge in graph")
  2000  	}
  2001  	if isZombie {
  2002  		t.Fatal("edge was marked as zombie")
  2003  	}
  2004  
  2005  	_, _, has, isZombie, err = ctx.graph.HasChannelEdge(chanID2)
  2006  	if err != nil {
  2007  		t.Fatalf("error looking for edge: %v", chanID2)
  2008  	}
  2009  	if has {
  2010  		t.Fatalf("found edge in graph")
  2011  	}
  2012  	if isZombie {
  2013  		t.Fatal("reorged edge should not be marked as zombie")
  2014  	}
  2015  }
  2016  
  2017  // TestChansClosedOfflinePruneGraph tests that if channels we know of are
  2018  // closed while we're offline, then once we resume operation of the
  2019  // ChannelRouter, then the channels are properly pruned.
  2020  func TestRouterChansClosedOfflinePruneGraph(t *testing.T) {
  2021  	t.Parallel()
  2022  
  2023  	const startingBlockHeight = 101
  2024  	ctx, cleanUp := createTestCtxSingleNode(t, startingBlockHeight)
  2025  	defer cleanUp()
  2026  
  2027  	const chanValue = 10000
  2028  
  2029  	// First, we'll create a channel, to be mined shortly at height 102.
  2030  	block102 := &wire.MsgBlock{
  2031  		Transactions: []*wire.MsgTx{},
  2032  	}
  2033  	nextHeight := startingBlockHeight + 1
  2034  	fundingTx1, chanUTXO, chanID1, err := createChannelEdge(ctx,
  2035  		bitcoinKey1.SerializeCompressed(),
  2036  		bitcoinKey2.SerializeCompressed(),
  2037  		chanValue, uint32(nextHeight))
  2038  	if err != nil {
  2039  		t.Fatalf("unable create channel edge: %v", err)
  2040  	}
  2041  	block102.Transactions = append(block102.Transactions, fundingTx1)
  2042  	ctx.chain.addBlock(block102, uint32(nextHeight), rand.Uint32())
  2043  	ctx.chain.setBestBlock(int32(nextHeight))
  2044  	ctx.chainView.notifyBlock(block102.BlockHash(), uint32(nextHeight),
  2045  		[]*wire.MsgTx{}, t)
  2046  
  2047  	// We'll now create the edges and nodes within the database required
  2048  	// for the ChannelRouter to properly recognize the channel we added
  2049  	// above.
  2050  	node1, err := createTestNode()
  2051  	if err != nil {
  2052  		t.Fatalf("unable to create test node: %v", err)
  2053  	}
  2054  	node2, err := createTestNode()
  2055  	if err != nil {
  2056  		t.Fatalf("unable to create test node: %v", err)
  2057  	}
  2058  	edge1 := &channeldb.ChannelEdgeInfo{
  2059  		ChannelID:     chanID1.ToUint64(),
  2060  		NodeKey1Bytes: node1.PubKeyBytes,
  2061  		NodeKey2Bytes: node2.PubKeyBytes,
  2062  		AuthProof: &channeldb.ChannelAuthProof{
  2063  			NodeSig1Bytes:   testSig.Serialize(),
  2064  			NodeSig2Bytes:   testSig.Serialize(),
  2065  			DecredSig1Bytes: testSig.Serialize(),
  2066  			DecredSig2Bytes: testSig.Serialize(),
  2067  		},
  2068  	}
  2069  	copy(edge1.DecredKey1Bytes[:], bitcoinKey1.SerializeCompressed())
  2070  	copy(edge1.DecredKey2Bytes[:], bitcoinKey2.SerializeCompressed())
  2071  	if err := ctx.router.AddEdge(edge1); err != nil {
  2072  		t.Fatalf("unable to add edge: %v", err)
  2073  	}
  2074  
  2075  	// The router should now be aware of the channel we created above.
  2076  	_, _, hasChan, isZombie, err := ctx.graph.HasChannelEdge(chanID1.ToUint64())
  2077  	if err != nil {
  2078  		t.Fatalf("error looking for edge: %v", chanID1)
  2079  	}
  2080  	if !hasChan {
  2081  		t.Fatalf("could not find edge in graph")
  2082  	}
  2083  	if isZombie {
  2084  		t.Fatal("edge was marked as zombie")
  2085  	}
  2086  
  2087  	// With the transaction included, and the router's database state
  2088  	// updated, we'll now mine 5 additional blocks on top of it.
  2089  	for i := 0; i < 5; i++ {
  2090  		nextHeight++
  2091  
  2092  		block := &wire.MsgBlock{
  2093  			Transactions: []*wire.MsgTx{},
  2094  		}
  2095  		ctx.chain.addBlock(block, uint32(nextHeight), rand.Uint32())
  2096  		ctx.chain.setBestBlock(int32(nextHeight))
  2097  		ctx.chainView.notifyBlock(block.BlockHash(), uint32(nextHeight),
  2098  			[]*wire.MsgTx{}, t)
  2099  	}
  2100  
  2101  	// At this point, our starting height should be 107.
  2102  	_, chainHeight, err := ctx.chain.GetBestBlock()
  2103  	if err != nil {
  2104  		t.Fatalf("unable to get best block: %v", err)
  2105  	}
  2106  	if chainHeight != 107 {
  2107  		t.Fatalf("incorrect chain height: expected %v, got %v",
  2108  			107, chainHeight)
  2109  	}
  2110  
  2111  	// Next, we'll "shut down" the router in order to simulate downtime.
  2112  	if err := ctx.router.Stop(); err != nil {
  2113  		t.Fatalf("unable to shutdown router: %v", err)
  2114  	}
  2115  
  2116  	// While the router is "offline" we'll mine 5 additional blocks, with
  2117  	// the second block closing the channel we created above.
  2118  	for i := 0; i < 5; i++ {
  2119  		nextHeight++
  2120  
  2121  		block := &wire.MsgBlock{
  2122  			Transactions: []*wire.MsgTx{},
  2123  		}
  2124  
  2125  		if i == 2 {
  2126  			// For the second block, we'll add a transaction that
  2127  			// closes the channel we created above by spending the
  2128  			// output.
  2129  			closingTx := wire.NewMsgTx()
  2130  			closingTx.Version = 2
  2131  			closingTx.AddTxIn(&wire.TxIn{
  2132  				PreviousOutPoint: *chanUTXO,
  2133  			})
  2134  			block.Transactions = append(block.Transactions,
  2135  				closingTx)
  2136  		}
  2137  
  2138  		ctx.chain.addBlock(block, uint32(nextHeight), rand.Uint32())
  2139  		ctx.chain.setBestBlock(int32(nextHeight))
  2140  		ctx.chainView.notifyBlock(block.BlockHash(), uint32(nextHeight),
  2141  			[]*wire.MsgTx{}, t)
  2142  	}
  2143  
  2144  	// At this point, our starting height should be 112.
  2145  	_, chainHeight, err = ctx.chain.GetBestBlock()
  2146  	if err != nil {
  2147  		t.Fatalf("unable to get best block: %v", err)
  2148  	}
  2149  	if chainHeight != 112 {
  2150  		t.Fatalf("incorrect chain height: expected %v, got %v",
  2151  			112, chainHeight)
  2152  	}
  2153  
  2154  	// Now we'll re-start the ChannelRouter. It should recognize that it's
  2155  	// behind the main chain and prune all the blocks that it missed while
  2156  	// it was down.
  2157  	ctx.RestartRouter(t)
  2158  
  2159  	// At this point, the channel that was pruned should no longer be known
  2160  	// by the router.
  2161  	_, _, hasChan, isZombie, err = ctx.graph.HasChannelEdge(chanID1.ToUint64())
  2162  	if err != nil {
  2163  		t.Fatalf("error looking for edge: %v", chanID1)
  2164  	}
  2165  	if hasChan {
  2166  		t.Fatalf("channel was found in graph but shouldn't have been")
  2167  	}
  2168  	if isZombie {
  2169  		t.Fatal("closed channel should not be marked as zombie")
  2170  	}
  2171  }
  2172  
  2173  // TestPruneChannelGraphStaleEdges ensures that we properly prune stale edges
  2174  // from the channel graph.
  2175  func TestPruneChannelGraphStaleEdges(t *testing.T) {
  2176  	t.Parallel()
  2177  
  2178  	freshTimestamp := time.Now()
  2179  	staleTimestamp := time.Unix(0, 0)
  2180  
  2181  	// We'll create the following test graph so that two of the channels
  2182  	// are pruned.
  2183  	testChannels := []*testChannel{
  2184  		// No edges.
  2185  		{
  2186  			Node1:     &testChannelEnd{Alias: "a"},
  2187  			Node2:     &testChannelEnd{Alias: "b"},
  2188  			Capacity:  100000,
  2189  			ChannelID: 1,
  2190  		},
  2191  
  2192  		// Only one edge with a stale timestamp.
  2193  		{
  2194  			Node1: &testChannelEnd{
  2195  				Alias: "d",
  2196  				testChannelPolicy: &testChannelPolicy{
  2197  					LastUpdate: staleTimestamp,
  2198  				},
  2199  			},
  2200  			Node2:     &testChannelEnd{Alias: "b"},
  2201  			Capacity:  100000,
  2202  			ChannelID: 2,
  2203  		},
  2204  
  2205  		// Only one edge with a stale timestamp, but it's the source
  2206  		// node so it won't get pruned.
  2207  		{
  2208  			Node1: &testChannelEnd{
  2209  				Alias: "a",
  2210  				testChannelPolicy: &testChannelPolicy{
  2211  					LastUpdate: staleTimestamp,
  2212  				},
  2213  			},
  2214  			Node2:     &testChannelEnd{Alias: "b"},
  2215  			Capacity:  100000,
  2216  			ChannelID: 3,
  2217  		},
  2218  
  2219  		// Only one edge with a fresh timestamp.
  2220  		{
  2221  			Node1: &testChannelEnd{
  2222  				Alias: "a",
  2223  				testChannelPolicy: &testChannelPolicy{
  2224  					LastUpdate: freshTimestamp,
  2225  				},
  2226  			},
  2227  			Node2:     &testChannelEnd{Alias: "b"},
  2228  			Capacity:  100000,
  2229  			ChannelID: 4,
  2230  		},
  2231  
  2232  		// One edge fresh, one edge stale. This will be pruned with
  2233  		// strict pruning activated.
  2234  		{
  2235  			Node1: &testChannelEnd{
  2236  				Alias: "c",
  2237  				testChannelPolicy: &testChannelPolicy{
  2238  					LastUpdate: freshTimestamp,
  2239  				},
  2240  			},
  2241  			Node2: &testChannelEnd{
  2242  				Alias: "d",
  2243  				testChannelPolicy: &testChannelPolicy{
  2244  					LastUpdate: staleTimestamp,
  2245  				},
  2246  			},
  2247  			Capacity:  100000,
  2248  			ChannelID: 5,
  2249  		},
  2250  
  2251  		// Both edges fresh.
  2252  		symmetricTestChannel("g", "h", 100000, &testChannelPolicy{
  2253  			LastUpdate: freshTimestamp,
  2254  		}, 6),
  2255  
  2256  		// Both edges stale, only one pruned. This should be pruned for
  2257  		// both normal and strict pruning.
  2258  		symmetricTestChannel("e", "f", 100000, &testChannelPolicy{
  2259  			LastUpdate: staleTimestamp,
  2260  		}, 7),
  2261  	}
  2262  
  2263  	for _, strictPruning := range []bool{true, false} {
  2264  		// We'll create our test graph and router backed with these test
  2265  		// channels we've created.
  2266  		testGraph, err := createTestGraphFromChannels(
  2267  			true, testChannels, "a",
  2268  		)
  2269  		if err != nil {
  2270  			t.Fatalf("unable to create test graph: %v", err)
  2271  		}
  2272  		defer testGraph.cleanUp()
  2273  
  2274  		const startingHeight = 100
  2275  		ctx, cleanUp := createTestCtxFromGraphInstance(
  2276  			t, startingHeight, testGraph, strictPruning,
  2277  		)
  2278  		defer cleanUp()
  2279  
  2280  		// All of the channels should exist before pruning them.
  2281  		assertChannelsPruned(t, ctx.graph, testChannels)
  2282  
  2283  		// Proceed to prune the channels - only the last one should be pruned.
  2284  		if err := ctx.router.pruneZombieChans(); err != nil {
  2285  			t.Fatalf("unable to prune zombie channels: %v", err)
  2286  		}
  2287  
  2288  		// We expect channels that have either both edges stale, or one edge
  2289  		// stale with both known.
  2290  		var prunedChannels []uint64
  2291  		if strictPruning {
  2292  			prunedChannels = []uint64{2, 5, 7}
  2293  		} else {
  2294  			prunedChannels = []uint64{2, 7}
  2295  		}
  2296  		assertChannelsPruned(t, ctx.graph, testChannels, prunedChannels...)
  2297  	}
  2298  }
  2299  
  2300  // TestPruneChannelGraphDoubleDisabled test that we can properly prune channels
  2301  // with both edges disabled from our channel graph.
  2302  func TestPruneChannelGraphDoubleDisabled(t *testing.T) {
  2303  	t.Parallel()
  2304  
  2305  	t.Run("no_assumechannelvalid", func(t *testing.T) {
  2306  		testPruneChannelGraphDoubleDisabled(t, false)
  2307  	})
  2308  	t.Run("assumechannelvalid", func(t *testing.T) {
  2309  		testPruneChannelGraphDoubleDisabled(t, true)
  2310  	})
  2311  }
  2312  
  2313  func testPruneChannelGraphDoubleDisabled(t *testing.T, assumeValid bool) {
  2314  	// We'll create the following test graph so that only the last channel
  2315  	// is pruned. We'll use a fresh timestamp to ensure they're not pruned
  2316  	// according to that heuristic.
  2317  	timestamp := time.Now()
  2318  	testChannels := []*testChannel{
  2319  		// Channel from self shouldn't be pruned.
  2320  		symmetricTestChannel(
  2321  			"self", "a", 100000, &testChannelPolicy{
  2322  				LastUpdate: timestamp,
  2323  				Disabled:   true,
  2324  			}, 99,
  2325  		),
  2326  
  2327  		// No edges.
  2328  		{
  2329  			Node1:     &testChannelEnd{Alias: "a"},
  2330  			Node2:     &testChannelEnd{Alias: "b"},
  2331  			Capacity:  100000,
  2332  			ChannelID: 1,
  2333  		},
  2334  
  2335  		// Only one edge disabled.
  2336  		{
  2337  			Node1: &testChannelEnd{
  2338  				Alias: "a",
  2339  				testChannelPolicy: &testChannelPolicy{
  2340  					LastUpdate: timestamp,
  2341  					Disabled:   true,
  2342  				},
  2343  			},
  2344  			Node2:     &testChannelEnd{Alias: "b"},
  2345  			Capacity:  100000,
  2346  			ChannelID: 2,
  2347  		},
  2348  
  2349  		// Only one edge enabled.
  2350  		{
  2351  			Node1: &testChannelEnd{
  2352  				Alias: "a",
  2353  				testChannelPolicy: &testChannelPolicy{
  2354  					LastUpdate: timestamp,
  2355  					Disabled:   false,
  2356  				},
  2357  			},
  2358  			Node2:     &testChannelEnd{Alias: "b"},
  2359  			Capacity:  100000,
  2360  			ChannelID: 3,
  2361  		},
  2362  
  2363  		// One edge disabled, one edge enabled.
  2364  		{
  2365  			Node1: &testChannelEnd{
  2366  				Alias: "a",
  2367  				testChannelPolicy: &testChannelPolicy{
  2368  					LastUpdate: timestamp,
  2369  					Disabled:   true,
  2370  				},
  2371  			},
  2372  			Node2: &testChannelEnd{
  2373  				Alias: "b",
  2374  				testChannelPolicy: &testChannelPolicy{
  2375  					LastUpdate: timestamp,
  2376  					Disabled:   false,
  2377  				},
  2378  			},
  2379  			Capacity:  100000,
  2380  			ChannelID: 1,
  2381  		},
  2382  
  2383  		// Both edges enabled.
  2384  		symmetricTestChannel("c", "d", 100000, &testChannelPolicy{
  2385  			LastUpdate: timestamp,
  2386  			Disabled:   false,
  2387  		}, 2),
  2388  
  2389  		// Both edges disabled, only one pruned.
  2390  		symmetricTestChannel("e", "f", 100000, &testChannelPolicy{
  2391  			LastUpdate: timestamp,
  2392  			Disabled:   true,
  2393  		}, 3),
  2394  	}
  2395  
  2396  	// We'll create our test graph and router backed with these test
  2397  	// channels we've created.
  2398  	testGraph, err := createTestGraphFromChannels(
  2399  		true, testChannels, "self",
  2400  	)
  2401  	if err != nil {
  2402  		t.Fatalf("unable to create test graph: %v", err)
  2403  	}
  2404  	defer testGraph.cleanUp()
  2405  
  2406  	const startingHeight = 100
  2407  	ctx, cleanUp := createTestCtxFromGraphInstanceAssumeValid(
  2408  		t, startingHeight, testGraph, assumeValid, false,
  2409  	)
  2410  	defer cleanUp()
  2411  
  2412  	// All the channels should exist within the graph before pruning them
  2413  	// when not using AssumeChannelValid, otherwise we should have pruned
  2414  	// the last channel on startup.
  2415  	if !assumeValid {
  2416  		assertChannelsPruned(t, ctx.graph, testChannels)
  2417  	} else {
  2418  		// Sleep to allow the pruning to finish.
  2419  		time.Sleep(200 * time.Millisecond)
  2420  
  2421  		prunedChannel := testChannels[len(testChannels)-1].ChannelID
  2422  		assertChannelsPruned(t, ctx.graph, testChannels, prunedChannel)
  2423  	}
  2424  
  2425  	if err := ctx.router.pruneZombieChans(); err != nil {
  2426  		t.Fatalf("unable to prune zombie channels: %v", err)
  2427  	}
  2428  
  2429  	// If we attempted to prune them without AssumeChannelValid being set,
  2430  	// none should be pruned. Otherwise the last channel should still be
  2431  	// pruned.
  2432  	if !assumeValid {
  2433  		assertChannelsPruned(t, ctx.graph, testChannels)
  2434  	} else {
  2435  		prunedChannel := testChannels[len(testChannels)-1].ChannelID
  2436  		assertChannelsPruned(t, ctx.graph, testChannels, prunedChannel)
  2437  	}
  2438  }
  2439  
  2440  // TestFindPathFeeWeighting tests that the findPath method will properly prefer
  2441  // routes with lower fees over routes with lower time lock values. This is
  2442  // meant to exercise the fact that the internal findPath method ranks edges
  2443  // with the square of the total fee in order bias towards lower fees.
  2444  func TestFindPathFeeWeighting(t *testing.T) {
  2445  	t.Parallel()
  2446  
  2447  	const startingBlockHeight = 101
  2448  	ctx, cleanUp := createTestCtxFromFile(
  2449  		t, startingBlockHeight, basicGraphFilePath,
  2450  	)
  2451  	defer cleanUp()
  2452  
  2453  	var preImage [32]byte
  2454  	copy(preImage[:], bytes.Repeat([]byte{9}, 32))
  2455  
  2456  	sourceNode, err := ctx.graph.SourceNode()
  2457  	if err != nil {
  2458  		t.Fatalf("unable to fetch source node: %v", err)
  2459  	}
  2460  
  2461  	amt := lnwire.MilliAtom(100)
  2462  
  2463  	target := ctx.aliases["luoji"]
  2464  
  2465  	// We'll now attempt a path finding attempt using this set up. Due to
  2466  	// the edge weighting, we should select the direct path over the 2 hop
  2467  	// path even though the direct path has a higher potential time lock.
  2468  	path, err := dbFindPath(
  2469  		ctx.graph, nil, &mockBandwidthHints{},
  2470  		noRestrictions,
  2471  		testPathFindingConfig,
  2472  		sourceNode.PubKeyBytes, target, amt, 0,
  2473  	)
  2474  	if err != nil {
  2475  		t.Fatalf("unable to find path: %v", err)
  2476  	}
  2477  
  2478  	// The route that was chosen should be exactly one hop, and should be
  2479  	// directly to luoji.
  2480  	if len(path) != 1 {
  2481  		t.Fatalf("expected path length of 1, instead was: %v", len(path))
  2482  	}
  2483  	if path[0].ToNodePubKey() != ctx.aliases["luoji"] {
  2484  		t.Fatalf("wrong node: %v", path[0].ToNodePubKey())
  2485  	}
  2486  }
  2487  
  2488  // TestIsStaleNode tests that the IsStaleNode method properly detects stale
  2489  // node announcements.
  2490  func TestIsStaleNode(t *testing.T) {
  2491  	t.Parallel()
  2492  
  2493  	const startingBlockHeight = 101
  2494  	ctx, cleanUp := createTestCtxSingleNode(t, startingBlockHeight)
  2495  	defer cleanUp()
  2496  
  2497  	// Before we can insert a node in to the database, we need to create a
  2498  	// channel that it's linked to.
  2499  	var (
  2500  		pub1 [33]byte
  2501  		pub2 [33]byte
  2502  	)
  2503  	copy(pub1[:], priv1.PubKey().SerializeCompressed())
  2504  	copy(pub2[:], priv2.PubKey().SerializeCompressed())
  2505  
  2506  	fundingTx, _, chanID, err := createChannelEdge(ctx,
  2507  		bitcoinKey1.SerializeCompressed(),
  2508  		bitcoinKey2.SerializeCompressed(),
  2509  		10000, 500)
  2510  	if err != nil {
  2511  		t.Fatalf("unable to create channel edge: %v", err)
  2512  	}
  2513  	fundingBlock := &wire.MsgBlock{
  2514  		Transactions: []*wire.MsgTx{fundingTx},
  2515  	}
  2516  	ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight)
  2517  
  2518  	edge := &channeldb.ChannelEdgeInfo{
  2519  		ChannelID:       chanID.ToUint64(),
  2520  		NodeKey1Bytes:   pub1,
  2521  		NodeKey2Bytes:   pub2,
  2522  		DecredKey1Bytes: pub1,
  2523  		DecredKey2Bytes: pub2,
  2524  		AuthProof:       nil,
  2525  	}
  2526  	if err := ctx.router.AddEdge(edge); err != nil {
  2527  		t.Fatalf("unable to add edge: %v", err)
  2528  	}
  2529  
  2530  	// Before we add the node, if we query for staleness, we should get
  2531  	// false, as we haven't added the full node.
  2532  	updateTimeStamp := time.Unix(123, 0)
  2533  	if ctx.router.IsStaleNode(pub1, updateTimeStamp) {
  2534  		t.Fatalf("incorrectly detected node as stale")
  2535  	}
  2536  
  2537  	// With the node stub in the database, we'll add the fully node
  2538  	// announcement to the database.
  2539  	n1 := &channeldb.LightningNode{
  2540  		HaveNodeAnnouncement: true,
  2541  		LastUpdate:           updateTimeStamp,
  2542  		Addresses:            testAddrs,
  2543  		Color:                color.RGBA{1, 2, 3, 0},
  2544  		Alias:                "node11",
  2545  		AuthSigBytes:         testSig.Serialize(),
  2546  		Features:             testFeatures,
  2547  	}
  2548  	copy(n1.PubKeyBytes[:], priv1.PubKey().SerializeCompressed())
  2549  	if err := ctx.router.AddNode(n1); err != nil {
  2550  		t.Fatalf("could not add node: %v", err)
  2551  	}
  2552  
  2553  	// If we use the same timestamp and query for staleness, we should get
  2554  	// true.
  2555  	if !ctx.router.IsStaleNode(pub1, updateTimeStamp) {
  2556  		t.Fatalf("failure to detect stale node update")
  2557  	}
  2558  
  2559  	// If we update the timestamp and once again query for staleness, it
  2560  	// should report false.
  2561  	newTimeStamp := time.Unix(1234, 0)
  2562  	if ctx.router.IsStaleNode(pub1, newTimeStamp) {
  2563  		t.Fatalf("incorrectly detected node as stale")
  2564  	}
  2565  }
  2566  
  2567  // TestIsKnownEdge tests that the IsKnownEdge method properly detects stale
  2568  // channel announcements.
  2569  func TestIsKnownEdge(t *testing.T) {
  2570  	t.Parallel()
  2571  
  2572  	const startingBlockHeight = 101
  2573  	ctx, cleanUp := createTestCtxSingleNode(t, startingBlockHeight)
  2574  	defer cleanUp()
  2575  
  2576  	// First, we'll create a new channel edge (just the info) and insert it
  2577  	// into the database.
  2578  	var (
  2579  		pub1 [33]byte
  2580  		pub2 [33]byte
  2581  	)
  2582  	copy(pub1[:], priv1.PubKey().SerializeCompressed())
  2583  	copy(pub2[:], priv2.PubKey().SerializeCompressed())
  2584  
  2585  	fundingTx, _, chanID, err := createChannelEdge(ctx,
  2586  		bitcoinKey1.SerializeCompressed(),
  2587  		bitcoinKey2.SerializeCompressed(),
  2588  		10000, 500)
  2589  	if err != nil {
  2590  		t.Fatalf("unable to create channel edge: %v", err)
  2591  	}
  2592  	fundingBlock := &wire.MsgBlock{
  2593  		Transactions: []*wire.MsgTx{fundingTx},
  2594  	}
  2595  	ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight)
  2596  
  2597  	edge := &channeldb.ChannelEdgeInfo{
  2598  		ChannelID:       chanID.ToUint64(),
  2599  		NodeKey1Bytes:   pub1,
  2600  		NodeKey2Bytes:   pub2,
  2601  		DecredKey1Bytes: pub1,
  2602  		DecredKey2Bytes: pub2,
  2603  		AuthProof:       nil,
  2604  	}
  2605  	if err := ctx.router.AddEdge(edge); err != nil {
  2606  		t.Fatalf("unable to add edge: %v", err)
  2607  	}
  2608  
  2609  	// Now that the edge has been inserted, query is the router already
  2610  	// knows of the edge should return true.
  2611  	if !ctx.router.IsKnownEdge(*chanID) {
  2612  		t.Fatalf("router should detect edge as known")
  2613  	}
  2614  }
  2615  
  2616  // TestIsStaleEdgePolicy tests that the IsStaleEdgePolicy properly detects
  2617  // stale channel edge update announcements.
  2618  func TestIsStaleEdgePolicy(t *testing.T) {
  2619  	t.Parallel()
  2620  
  2621  	const startingBlockHeight = 101
  2622  	ctx, cleanUp := createTestCtxFromFile(
  2623  		t, startingBlockHeight, basicGraphFilePath,
  2624  	)
  2625  	defer cleanUp()
  2626  
  2627  	// First, we'll create a new channel edge (just the info) and insert it
  2628  	// into the database.
  2629  	var (
  2630  		pub1 [33]byte
  2631  		pub2 [33]byte
  2632  	)
  2633  	copy(pub1[:], priv1.PubKey().SerializeCompressed())
  2634  	copy(pub2[:], priv2.PubKey().SerializeCompressed())
  2635  
  2636  	fundingTx, _, chanID, err := createChannelEdge(ctx,
  2637  		bitcoinKey1.SerializeCompressed(),
  2638  		bitcoinKey2.SerializeCompressed(),
  2639  		10000, 500)
  2640  	if err != nil {
  2641  		t.Fatalf("unable to create channel edge: %v", err)
  2642  	}
  2643  	fundingBlock := &wire.MsgBlock{
  2644  		Transactions: []*wire.MsgTx{fundingTx},
  2645  	}
  2646  	ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight)
  2647  
  2648  	// If we query for staleness before adding the edge, we should get
  2649  	// false.
  2650  	updateTimeStamp := time.Unix(123, 0)
  2651  	if ctx.router.IsStaleEdgePolicy(*chanID, updateTimeStamp, 0) {
  2652  		t.Fatalf("router failed to detect fresh edge policy")
  2653  	}
  2654  	if ctx.router.IsStaleEdgePolicy(*chanID, updateTimeStamp, 1) {
  2655  		t.Fatalf("router failed to detect fresh edge policy")
  2656  	}
  2657  
  2658  	edge := &channeldb.ChannelEdgeInfo{
  2659  		ChannelID:       chanID.ToUint64(),
  2660  		NodeKey1Bytes:   pub1,
  2661  		NodeKey2Bytes:   pub2,
  2662  		DecredKey1Bytes: pub1,
  2663  		DecredKey2Bytes: pub2,
  2664  		AuthProof:       nil,
  2665  	}
  2666  	if err := ctx.router.AddEdge(edge); err != nil {
  2667  		t.Fatalf("unable to add edge: %v", err)
  2668  	}
  2669  
  2670  	// We'll also add two edge policies, one for each direction.
  2671  	edgePolicy := &channeldb.ChannelEdgePolicy{
  2672  		SigBytes:                  testSig.Serialize(),
  2673  		ChannelID:                 edge.ChannelID,
  2674  		LastUpdate:                updateTimeStamp,
  2675  		TimeLockDelta:             10,
  2676  		MinHTLC:                   1,
  2677  		FeeBaseMAtoms:             10,
  2678  		FeeProportionalMillionths: 10000,
  2679  	}
  2680  	edgePolicy.ChannelFlags = 0
  2681  	if err := ctx.router.UpdateEdge(edgePolicy); err != nil {
  2682  		t.Fatalf("unable to update edge policy: %v", err)
  2683  	}
  2684  
  2685  	edgePolicy = &channeldb.ChannelEdgePolicy{
  2686  		SigBytes:                  testSig.Serialize(),
  2687  		ChannelID:                 edge.ChannelID,
  2688  		LastUpdate:                updateTimeStamp,
  2689  		TimeLockDelta:             10,
  2690  		MinHTLC:                   1,
  2691  		FeeBaseMAtoms:             10,
  2692  		FeeProportionalMillionths: 10000,
  2693  	}
  2694  	edgePolicy.ChannelFlags = 1
  2695  	if err := ctx.router.UpdateEdge(edgePolicy); err != nil {
  2696  		t.Fatalf("unable to update edge policy: %v", err)
  2697  	}
  2698  
  2699  	// Now that the edges have been added, an identical (chanID, flag,
  2700  	// timestamp) tuple for each edge should be detected as a stale edge.
  2701  	if !ctx.router.IsStaleEdgePolicy(*chanID, updateTimeStamp, 0) {
  2702  		t.Fatalf("router failed to detect stale edge policy")
  2703  	}
  2704  	if !ctx.router.IsStaleEdgePolicy(*chanID, updateTimeStamp, 1) {
  2705  		t.Fatalf("router failed to detect stale edge policy")
  2706  	}
  2707  
  2708  	// If we now update the timestamp for both edges, the router should
  2709  	// detect that this tuple represents a fresh edge.
  2710  	updateTimeStamp = time.Unix(9999, 0)
  2711  	if ctx.router.IsStaleEdgePolicy(*chanID, updateTimeStamp, 0) {
  2712  		t.Fatalf("router failed to detect fresh edge policy")
  2713  	}
  2714  	if ctx.router.IsStaleEdgePolicy(*chanID, updateTimeStamp, 1) {
  2715  		t.Fatalf("router failed to detect fresh edge policy")
  2716  	}
  2717  }
  2718  
  2719  // TestEmptyRoutesGenerateSphinxPacket tests that the generateSphinxPacket
  2720  // function is able to gracefully handle being passed a nil set of hops for the
  2721  // route by the caller.
  2722  func TestEmptyRoutesGenerateSphinxPacket(t *testing.T) {
  2723  	t.Parallel()
  2724  
  2725  	sessionKey, _ := secp256k1.GeneratePrivateKey()
  2726  	emptyRoute := &route.Route{}
  2727  	_, _, err := generateSphinxPacket(emptyRoute, testHash[:], sessionKey)
  2728  	if err != route.ErrNoRouteHopsProvided {
  2729  		t.Fatalf("expected empty hops error: instead got: %v", err)
  2730  	}
  2731  }
  2732  
  2733  // TestUnknownErrorSource tests that if the source of an error is unknown, all
  2734  // edges along the route will be pruned.
  2735  func TestUnknownErrorSource(t *testing.T) {
  2736  	t.Parallel()
  2737  
  2738  	// Setup a network. It contains two paths to c: a->b->c and an
  2739  	// alternative a->d->c.
  2740  	chanCapSat := dcrutil.Amount(100000)
  2741  	testChannels := []*testChannel{
  2742  		symmetricTestChannel("a", "b", chanCapSat, &testChannelPolicy{
  2743  			Expiry:  144,
  2744  			FeeRate: 400,
  2745  			MinHTLC: 1,
  2746  			MaxHTLC: lnwire.NewMAtomsFromAtoms(chanCapSat),
  2747  		}, 1),
  2748  		symmetricTestChannel("b", "c", chanCapSat, &testChannelPolicy{
  2749  			Expiry:  144,
  2750  			FeeRate: 400,
  2751  			MinHTLC: 1,
  2752  			MaxHTLC: lnwire.NewMAtomsFromAtoms(chanCapSat),
  2753  		}, 3),
  2754  		symmetricTestChannel("a", "d", chanCapSat, &testChannelPolicy{
  2755  			Expiry:        144,
  2756  			FeeRate:       400,
  2757  			FeeBaseMAtoms: 100000,
  2758  			MinHTLC:       1,
  2759  			MaxHTLC:       lnwire.NewMAtomsFromAtoms(chanCapSat),
  2760  		}, 2),
  2761  		symmetricTestChannel("d", "c", chanCapSat, &testChannelPolicy{
  2762  			Expiry:        144,
  2763  			FeeRate:       400,
  2764  			FeeBaseMAtoms: 100000,
  2765  			MinHTLC:       1,
  2766  			MaxHTLC:       lnwire.NewMAtomsFromAtoms(chanCapSat),
  2767  		}, 4),
  2768  	}
  2769  
  2770  	testGraph, err := createTestGraphFromChannels(true, testChannels, "a")
  2771  	defer testGraph.cleanUp()
  2772  	if err != nil {
  2773  		t.Fatalf("unable to create graph: %v", err)
  2774  	}
  2775  
  2776  	const startingBlockHeight = 101
  2777  	ctx, cleanUp := createTestCtxFromGraphInstance(
  2778  		t, startingBlockHeight, testGraph, false,
  2779  	)
  2780  	defer cleanUp()
  2781  
  2782  	// Create a payment to node c.
  2783  	var payHash lntypes.Hash
  2784  	payment := LightningPayment{
  2785  		Target:      ctx.aliases["c"],
  2786  		Amount:      lnwire.NewMAtomsFromAtoms(1000),
  2787  		FeeLimit:    noFeeLimit,
  2788  		paymentHash: &payHash,
  2789  	}
  2790  
  2791  	// We'll modify the SendToSwitch method so that it simulates hop b as a
  2792  	// node that returns an unparsable failure if approached via the a->b
  2793  	// channel.
  2794  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
  2795  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
  2796  
  2797  			// If channel a->b is used, return an error without
  2798  			// source and message. The sender won't know the origin
  2799  			// of the error.
  2800  			if firstHop.ToUint64() == 1 {
  2801  				return [32]byte{},
  2802  					htlcswitch.ErrUnreadableFailureMessage
  2803  			}
  2804  
  2805  			// Otherwise the payment succeeds.
  2806  			return lntypes.Preimage{}, nil
  2807  		})
  2808  
  2809  	// Send off the payment request to the router. The expectation is that
  2810  	// the route a->b->c is tried first. An unreadable faiure is returned
  2811  	// which should pruning the channel a->b. We expect the payment to
  2812  	// succeed via a->d.
  2813  	_, _, err = ctx.router.SendPayment(&payment)
  2814  	if err != nil {
  2815  		t.Fatalf("expected payment to succeed, but got: %v", err)
  2816  	}
  2817  
  2818  	// Next we modify payment result to return an unknown failure.
  2819  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
  2820  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
  2821  
  2822  			// If channel a->b is used, simulate that the failure
  2823  			// couldn't be decoded (FailureMessage is nil).
  2824  			if firstHop.ToUint64() == 2 {
  2825  				return [32]byte{},
  2826  					htlcswitch.NewUnknownForwardingError(1)
  2827  			}
  2828  
  2829  			// Otherwise the payment succeeds.
  2830  			return lntypes.Preimage{}, nil
  2831  		})
  2832  
  2833  	// Send off the payment request to the router. We expect the payment to
  2834  	// fail because both routes have been pruned.
  2835  	payHash = lntypes.Hash{1}
  2836  	payment.paymentHash = &payHash
  2837  	_, _, err = ctx.router.SendPayment(&payment)
  2838  	if err == nil {
  2839  		t.Fatalf("expected payment to fail")
  2840  	}
  2841  }
  2842  
  2843  // assertChannelsPruned ensures that only the given channels are pruned from the
  2844  // graph out of the set of all channels.
  2845  func assertChannelsPruned(t *testing.T, graph *channeldb.ChannelGraph,
  2846  	channels []*testChannel, prunedChanIDs ...uint64) {
  2847  
  2848  	t.Helper()
  2849  
  2850  	pruned := make(map[uint64]struct{}, len(channels))
  2851  	for _, chanID := range prunedChanIDs {
  2852  		pruned[chanID] = struct{}{}
  2853  	}
  2854  
  2855  	for _, channel := range channels {
  2856  		_, shouldPrune := pruned[channel.ChannelID]
  2857  		_, _, exists, isZombie, err := graph.HasChannelEdge(
  2858  			channel.ChannelID,
  2859  		)
  2860  		if err != nil {
  2861  			t.Fatalf("unable to determine existence of "+
  2862  				"channel=%v in the graph: %v",
  2863  				channel.ChannelID, err)
  2864  		}
  2865  		if !shouldPrune && !exists {
  2866  			t.Fatalf("expected channel=%v to exist within "+
  2867  				"the graph", channel.ChannelID)
  2868  		}
  2869  		if shouldPrune && exists {
  2870  			t.Fatalf("expected channel=%v to not exist "+
  2871  				"within the graph", channel.ChannelID)
  2872  		}
  2873  		if !shouldPrune && isZombie {
  2874  			t.Fatalf("expected channel=%v to not be marked "+
  2875  				"as zombie", channel.ChannelID)
  2876  		}
  2877  		if shouldPrune && !isZombie {
  2878  			t.Fatalf("expected channel=%v to be marked as "+
  2879  				"zombie", channel.ChannelID)
  2880  		}
  2881  	}
  2882  }
  2883  
  2884  // TestSendToRouteStructuredError asserts that SendToRoute returns a structured
  2885  // error.
  2886  func TestSendToRouteStructuredError(t *testing.T) {
  2887  	t.Parallel()
  2888  
  2889  	// Setup a three node network.
  2890  	chanCapSat := dcrutil.Amount(100000)
  2891  	testChannels := []*testChannel{
  2892  		symmetricTestChannel("a", "b", chanCapSat, &testChannelPolicy{
  2893  			Expiry:  144,
  2894  			FeeRate: 400,
  2895  			MinHTLC: 1,
  2896  			MaxHTLC: lnwire.NewMAtomsFromAtoms(chanCapSat),
  2897  		}, 1),
  2898  		symmetricTestChannel("b", "c", chanCapSat, &testChannelPolicy{
  2899  			Expiry:  144,
  2900  			FeeRate: 400,
  2901  			MinHTLC: 1,
  2902  			MaxHTLC: lnwire.NewMAtomsFromAtoms(chanCapSat),
  2903  		}, 2),
  2904  	}
  2905  
  2906  	testGraph, err := createTestGraphFromChannels(true, testChannels, "a")
  2907  	if err != nil {
  2908  		t.Fatalf("unable to create graph: %v", err)
  2909  	}
  2910  	defer testGraph.cleanUp()
  2911  
  2912  	const startingBlockHeight = 101
  2913  	ctx, cleanUp := createTestCtxFromGraphInstance(
  2914  		t, startingBlockHeight, testGraph, false,
  2915  	)
  2916  	defer cleanUp()
  2917  
  2918  	// Set up an init channel for the control tower, such that we can make
  2919  	// sure the payment is initiated correctly.
  2920  	init := make(chan initArgs, 1)
  2921  	ctx.router.cfg.Control.(*mockControlTowerOld).init = init
  2922  
  2923  	// Setup a route from source a to destination c. The route will be used
  2924  	// in a call to SendToRoute. SendToRoute also applies channel updates,
  2925  	// but it saves us from including RequestRoute in the test scope too.
  2926  	const payAmt = lnwire.MilliAtom(10000)
  2927  	hop1 := ctx.aliases["b"]
  2928  	hop2 := ctx.aliases["c"]
  2929  	hops := []*route.Hop{
  2930  		{
  2931  			ChannelID:     1,
  2932  			PubKeyBytes:   hop1,
  2933  			AmtToForward:  payAmt,
  2934  			LegacyPayload: true,
  2935  		},
  2936  		{
  2937  			ChannelID:     2,
  2938  			PubKeyBytes:   hop2,
  2939  			AmtToForward:  payAmt,
  2940  			LegacyPayload: true,
  2941  		},
  2942  	}
  2943  
  2944  	rt, err := route.NewRouteFromHops(payAmt, 100, ctx.aliases["a"], hops)
  2945  	if err != nil {
  2946  		t.Fatalf("unable to create route: %v", err)
  2947  	}
  2948  
  2949  	finalHopIndex := len(hops)
  2950  	testCases := map[int]lnwire.FailureMessage{
  2951  		finalHopIndex: lnwire.NewFailIncorrectDetails(payAmt, 100),
  2952  		1: &lnwire.FailFeeInsufficient{
  2953  			Update: lnwire.ChannelUpdate{},
  2954  		},
  2955  	}
  2956  
  2957  	for failIndex, errorType := range testCases {
  2958  		failIndex := failIndex
  2959  		errorType := errorType
  2960  
  2961  		t.Run(fmt.Sprintf("%T", errorType), func(t *testing.T) {
  2962  			// We'll modify the SendToSwitch method so that it
  2963  			// simulates a failed payment with an error originating
  2964  			// from the final hop in the route.
  2965  			ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
  2966  				func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
  2967  					return [32]byte{}, htlcswitch.NewForwardingError(
  2968  						errorType, failIndex,
  2969  					)
  2970  				},
  2971  			)
  2972  
  2973  			// The payment parameter is mostly redundant in
  2974  			// SendToRoute.  Can be left empty for this test.
  2975  			var payment lntypes.Hash
  2976  
  2977  			// Send off the payment request to the router. The
  2978  			// specified route should be attempted and the channel
  2979  			// update should be received by router and ignored
  2980  			// because it is missing a valid
  2981  			// signature.
  2982  			_, err = ctx.router.SendToRoute(payment, rt)
  2983  
  2984  			fErr, ok := err.(*htlcswitch.ForwardingError)
  2985  			require.True(
  2986  				t, ok, "expected forwarding error, got: %T", err,
  2987  			)
  2988  
  2989  			require.IsType(
  2990  				t, errorType, fErr.WireMessage(),
  2991  				"expected type %T got %T", errorType,
  2992  				fErr.WireMessage(),
  2993  			)
  2994  
  2995  			// Check that the correct values were used when
  2996  			// initiating the payment.
  2997  			select {
  2998  			case initVal := <-init:
  2999  				if initVal.c.Value != payAmt {
  3000  					t.Fatalf("expected %v, got %v", payAmt,
  3001  						initVal.c.Value)
  3002  				}
  3003  			case <-time.After(100 * time.Millisecond):
  3004  				t.Fatalf("initPayment not called")
  3005  			}
  3006  		})
  3007  	}
  3008  }
  3009  
  3010  // TestSendToRouteMultiShardSend checks that a 3-shard payment can be executed
  3011  // using SendToRoute.
  3012  func TestSendToRouteMultiShardSend(t *testing.T) {
  3013  	t.Parallel()
  3014  
  3015  	ctx, cleanup := createTestCtxSingleNode(t, 0)
  3016  	defer cleanup()
  3017  
  3018  	const numShards = 3
  3019  	const payAmt = lnwire.MilliAtom(numShards * 10000)
  3020  	node, err := createTestNode()
  3021  	if err != nil {
  3022  		t.Fatal(err)
  3023  	}
  3024  
  3025  	// Create a simple 1-hop route that we will use for all three shards.
  3026  	hops := []*route.Hop{
  3027  		{
  3028  			ChannelID:    1,
  3029  			PubKeyBytes:  node.PubKeyBytes,
  3030  			AmtToForward: payAmt / numShards,
  3031  			MPP:          record.NewMPP(payAmt, [32]byte{}),
  3032  		},
  3033  	}
  3034  
  3035  	sourceNode, err := ctx.graph.SourceNode()
  3036  	if err != nil {
  3037  		t.Fatal(err)
  3038  	}
  3039  
  3040  	rt, err := route.NewRouteFromHops(
  3041  		payAmt, 100, sourceNode.PubKeyBytes, hops,
  3042  	)
  3043  	if err != nil {
  3044  		t.Fatalf("unable to create route: %v", err)
  3045  	}
  3046  
  3047  	// The first shard we send we'll fail immediately, to check that we are
  3048  	// still allowed to retry with other shards after a failed one.
  3049  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
  3050  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
  3051  			return [32]byte{}, htlcswitch.NewForwardingError(
  3052  				&lnwire.FailFeeInsufficient{
  3053  					Update: lnwire.ChannelUpdate{},
  3054  				}, 1,
  3055  			)
  3056  		})
  3057  
  3058  	// The payment parameter is mostly redundant in SendToRoute. Can be left
  3059  	// empty for this test.
  3060  	var payment lntypes.Hash
  3061  
  3062  	// Send the shard using the created route, and expect an error to be
  3063  	// returned.
  3064  	_, err = ctx.router.SendToRoute(payment, rt)
  3065  	if err == nil {
  3066  		t.Fatalf("expected forwarding error")
  3067  	}
  3068  
  3069  	// Now we'll modify the SendToSwitch method again to wait until all
  3070  	// three shards are initiated before returning a result. We do this by
  3071  	// signalling when the method has been called, and then stop to wait
  3072  	// for the test to deliver the final result on the channel below.
  3073  	waitForResultSignal := make(chan struct{}, numShards)
  3074  	results := make(chan lntypes.Preimage, numShards)
  3075  
  3076  	ctx.router.cfg.Payer.(*mockPaymentAttemptDispatcherOld).setPaymentResult(
  3077  		func(firstHop lnwire.ShortChannelID) ([32]byte, error) {
  3078  
  3079  			// Signal that the shard has been initiated and is
  3080  			// waiting for a result.
  3081  			waitForResultSignal <- struct{}{}
  3082  
  3083  			// Wait for a result before returning it.
  3084  			res, ok := <-results
  3085  			if !ok {
  3086  				return [32]byte{}, fmt.Errorf("failure")
  3087  			}
  3088  			return res, nil
  3089  		})
  3090  
  3091  	// Launch three shards by calling SendToRoute in three goroutines,
  3092  	// returning their final error on the channel.
  3093  	errChan := make(chan error)
  3094  	successes := make(chan lntypes.Preimage)
  3095  
  3096  	for i := 0; i < numShards; i++ {
  3097  		go func() {
  3098  			attempt, err := ctx.router.SendToRoute(payment, rt)
  3099  			if err != nil {
  3100  				errChan <- err
  3101  				return
  3102  			}
  3103  
  3104  			successes <- attempt.Settle.Preimage
  3105  		}()
  3106  	}
  3107  
  3108  	// Wait for all shards to signal they have been initiated.
  3109  	for i := 0; i < numShards; i++ {
  3110  		select {
  3111  		case <-waitForResultSignal:
  3112  		case <-time.After(5 * time.Second):
  3113  			t.Fatalf("not waiting for results")
  3114  		}
  3115  	}
  3116  
  3117  	// Deliver a dummy preimage to all the shard handlers.
  3118  	preimage := lntypes.Preimage{}
  3119  	preimage[4] = 42
  3120  	for i := 0; i < numShards; i++ {
  3121  		results <- preimage
  3122  	}
  3123  
  3124  	// Finally expect all shards to return with the above preimage.
  3125  	for i := 0; i < numShards; i++ {
  3126  		select {
  3127  		case p := <-successes:
  3128  			if p != preimage {
  3129  				t.Fatalf("preimage mismatch")
  3130  			}
  3131  		case err := <-errChan:
  3132  			t.Fatalf("unexpected error from SendToRoute: %v", err)
  3133  		case <-time.After(5 * time.Second):
  3134  			t.Fatalf("result not received")
  3135  		}
  3136  	}
  3137  }
  3138  
  3139  // TestSendToRouteMaxHops asserts that SendToRoute fails when using a route that
  3140  // exceeds the maximum number of hops.
  3141  func TestSendToRouteMaxHops(t *testing.T) {
  3142  	t.Parallel()
  3143  
  3144  	// Setup a two node network.
  3145  	chanCapSat := dcrutil.Amount(100000)
  3146  	testChannels := []*testChannel{
  3147  		symmetricTestChannel("a", "b", chanCapSat, &testChannelPolicy{
  3148  			Expiry:  144,
  3149  			FeeRate: 400,
  3150  			MinHTLC: 1,
  3151  			MaxHTLC: lnwire.NewMAtomsFromAtoms(chanCapSat),
  3152  		}, 1),
  3153  	}
  3154  
  3155  	testGraph, err := createTestGraphFromChannels(true, testChannels, "a")
  3156  	if err != nil {
  3157  		t.Fatalf("unable to create graph: %v", err)
  3158  	}
  3159  	defer testGraph.cleanUp()
  3160  
  3161  	const startingBlockHeight = 101
  3162  
  3163  	ctx, cleanUp := createTestCtxFromGraphInstance(
  3164  		t, startingBlockHeight, testGraph, false,
  3165  	)
  3166  	defer cleanUp()
  3167  
  3168  	// Create a 30 hop route that exceeds the maximum hop limit.
  3169  	const payAmt = lnwire.MilliAtom(10000)
  3170  	hopA := ctx.aliases["a"]
  3171  	hopB := ctx.aliases["b"]
  3172  
  3173  	var hops []*route.Hop
  3174  	for i := 0; i < 15; i++ {
  3175  		hops = append(hops, &route.Hop{
  3176  			ChannelID:     1,
  3177  			PubKeyBytes:   hopB,
  3178  			AmtToForward:  payAmt,
  3179  			LegacyPayload: true,
  3180  		})
  3181  
  3182  		hops = append(hops, &route.Hop{
  3183  			ChannelID:     1,
  3184  			PubKeyBytes:   hopA,
  3185  			AmtToForward:  payAmt,
  3186  			LegacyPayload: true,
  3187  		})
  3188  	}
  3189  
  3190  	rt, err := route.NewRouteFromHops(payAmt, 100, ctx.aliases["a"], hops)
  3191  	if err != nil {
  3192  		t.Fatalf("unable to create route: %v", err)
  3193  	}
  3194  
  3195  	// Send off the payment request to the router. We expect an error back
  3196  	// indicating that the route is too long.
  3197  	var payment lntypes.Hash
  3198  	_, err = ctx.router.SendToRoute(payment, rt)
  3199  	if err != route.ErrMaxRouteHopsExceeded {
  3200  		t.Fatalf("expected ErrMaxRouteHopsExceeded, but got %v", err)
  3201  	}
  3202  }
  3203  
  3204  // TestBuildRoute tests whether correct routes are built.
  3205  func TestBuildRoute(t *testing.T) {
  3206  	// Setup a three node network.
  3207  	chanCapSat := dcrutil.Amount(100000)
  3208  	paymentAddrFeatures := lnwire.NewFeatureVector(
  3209  		lnwire.NewRawFeatureVector(lnwire.PaymentAddrOptional),
  3210  		lnwire.Features,
  3211  	)
  3212  	testChannels := []*testChannel{
  3213  		// Create two local channels from a. The bandwidth is estimated
  3214  		// in this test as the channel capacity. For building routes, we
  3215  		// expected the channel with the largest estimated bandwidth to
  3216  		// be selected.
  3217  		symmetricTestChannel("a", "b", chanCapSat, &testChannelPolicy{
  3218  			Expiry:  144,
  3219  			FeeRate: 20000,
  3220  			MinHTLC: lnwire.NewMAtomsFromAtoms(5),
  3221  			MaxHTLC: lnwire.NewMAtomsFromAtoms(chanCapSat),
  3222  		}, 1),
  3223  		symmetricTestChannel("a", "b", chanCapSat/2, &testChannelPolicy{
  3224  			Expiry:  144,
  3225  			FeeRate: 20000,
  3226  			MinHTLC: lnwire.NewMAtomsFromAtoms(5),
  3227  			MaxHTLC: lnwire.NewMAtomsFromAtoms(chanCapSat / 2),
  3228  		}, 6),
  3229  
  3230  		// Create two channels from b to c. For building routes, we
  3231  		// expect the lowest cost channel to be selected. Note that this
  3232  		// isn't a situation that we are expecting in reality. Routing
  3233  		// nodes are recommended to keep their channel policies towards
  3234  		// the same peer identical.
  3235  		symmetricTestChannel("b", "c", chanCapSat, &testChannelPolicy{
  3236  			Expiry:   144,
  3237  			FeeRate:  50000,
  3238  			MinHTLC:  lnwire.NewMAtomsFromAtoms(20),
  3239  			MaxHTLC:  lnwire.NewMAtomsFromAtoms(120),
  3240  			Features: paymentAddrFeatures,
  3241  		}, 2),
  3242  		symmetricTestChannel("b", "c", chanCapSat, &testChannelPolicy{
  3243  			Expiry:   144,
  3244  			FeeRate:  60000,
  3245  			MinHTLC:  lnwire.NewMAtomsFromAtoms(20),
  3246  			MaxHTLC:  lnwire.NewMAtomsFromAtoms(120),
  3247  			Features: paymentAddrFeatures,
  3248  		}, 7),
  3249  
  3250  		symmetricTestChannel("a", "e", chanCapSat, &testChannelPolicy{
  3251  			Expiry:   144,
  3252  			FeeRate:  80000,
  3253  			MinHTLC:  lnwire.NewMAtomsFromAtoms(5),
  3254  			MaxHTLC:  lnwire.NewMAtomsFromAtoms(10),
  3255  			Features: paymentAddrFeatures,
  3256  		}, 5),
  3257  		symmetricTestChannel("e", "c", chanCapSat, &testChannelPolicy{
  3258  			Expiry:   144,
  3259  			FeeRate:  100000,
  3260  			MinHTLC:  lnwire.NewMAtomsFromAtoms(20),
  3261  			MaxHTLC:  lnwire.NewMAtomsFromAtoms(chanCapSat),
  3262  			Features: paymentAddrFeatures,
  3263  		}, 4),
  3264  	}
  3265  
  3266  	testGraph, err := createTestGraphFromChannels(true, testChannels, "a")
  3267  	if err != nil {
  3268  		t.Fatalf("unable to create graph: %v", err)
  3269  	}
  3270  	defer testGraph.cleanUp()
  3271  
  3272  	const startingBlockHeight = 101
  3273  
  3274  	ctx, cleanUp := createTestCtxFromGraphInstance(
  3275  		t, startingBlockHeight, testGraph, false,
  3276  	)
  3277  	defer cleanUp()
  3278  
  3279  	checkHops := func(rt *route.Route, expected []uint64,
  3280  		payAddr [32]byte) {
  3281  
  3282  		t.Helper()
  3283  
  3284  		if len(rt.Hops) != len(expected) {
  3285  			t.Fatal("hop count mismatch")
  3286  		}
  3287  		for i, hop := range rt.Hops {
  3288  			if hop.ChannelID != expected[i] {
  3289  				t.Fatalf("expected channel %v at pos %v, but "+
  3290  					"got channel %v",
  3291  					expected[i], i, hop.ChannelID)
  3292  			}
  3293  		}
  3294  
  3295  		lastHop := rt.Hops[len(rt.Hops)-1]
  3296  		require.NotNil(t, lastHop.MPP)
  3297  		require.Equal(t, lastHop.MPP.PaymentAddr(), payAddr)
  3298  	}
  3299  
  3300  	var payAddr [32]byte
  3301  	_, err = rand.Read(payAddr[:])
  3302  	require.NoError(t, err)
  3303  
  3304  	// Create hop list from the route node pubkeys.
  3305  	hops := []route.Vertex{
  3306  		ctx.aliases["b"], ctx.aliases["c"],
  3307  	}
  3308  	amt := lnwire.NewMAtomsFromAtoms(100)
  3309  
  3310  	// Build the route for the given amount.
  3311  	rt, err := ctx.router.BuildRoute(
  3312  		&amt, hops, nil, 40, &payAddr,
  3313  	)
  3314  	if err != nil {
  3315  		t.Fatal(err)
  3316  	}
  3317  
  3318  	// Check that we get the expected route back. The total amount should be
  3319  	// the amount to deliver to hop c (100 sats) plus the max fee for the
  3320  	// connection b->c (6 sats).
  3321  	checkHops(rt, []uint64{1, 7}, payAddr)
  3322  	if rt.TotalAmount != 106000 {
  3323  		t.Fatalf("unexpected total amount %v", rt.TotalAmount)
  3324  	}
  3325  
  3326  	// Build the route for the minimum amount.
  3327  	rt, err = ctx.router.BuildRoute(
  3328  		nil, hops, nil, 40, &payAddr,
  3329  	)
  3330  	if err != nil {
  3331  		t.Fatal(err)
  3332  	}
  3333  
  3334  	// Check that we get the expected route back. The minimum that we can
  3335  	// send from b to c is 20 sats. Hop b charges 1200 msat for the
  3336  	// forwarding. The channel between hop a and b can carry amounts in the
  3337  	// range [5, 100], so 21200 msats is the minimum amount for this route.
  3338  	checkHops(rt, []uint64{1, 7}, payAddr)
  3339  	if rt.TotalAmount != 21200 {
  3340  		t.Fatalf("unexpected total amount %v", rt.TotalAmount)
  3341  	}
  3342  
  3343  	// Test a route that contains incompatible channel htlc constraints.
  3344  	// There is no amount that can pass through both channel 5 and 4.
  3345  	hops = []route.Vertex{
  3346  		ctx.aliases["e"], ctx.aliases["c"],
  3347  	}
  3348  	_, err = ctx.router.BuildRoute(
  3349  		nil, hops, nil, 40, nil,
  3350  	)
  3351  	errNoChannel, ok := err.(ErrNoChannel)
  3352  	if !ok {
  3353  		t.Fatalf("expected incompatible policies error, but got %v",
  3354  			err)
  3355  	}
  3356  	if errNoChannel.position != 0 {
  3357  		t.Fatalf("unexpected no channel error position")
  3358  	}
  3359  	if errNoChannel.fromNode != ctx.aliases["a"] {
  3360  		t.Fatalf("unexpected no channel error node")
  3361  	}
  3362  }
  3363  
  3364  // edgeCreationModifier is an enum-like type used to modify steps that are
  3365  // skipped when creating a channel in the test context.
  3366  type edgeCreationModifier uint8
  3367  
  3368  const (
  3369  	// edgeCreationNoFundingTx is used to skip adding the funding
  3370  	// transaction of an edge to the chain.
  3371  	edgeCreationNoFundingTx edgeCreationModifier = iota
  3372  
  3373  	// edgeCreationNoUTXO is used to skip adding the UTXO of a channel to
  3374  	// the UTXO set.
  3375  	edgeCreationNoUTXO
  3376  
  3377  	// edgeCreationBadScript is used to create the edge, but use the wrong
  3378  	// scrip which should cause it to fail output validation.
  3379  	edgeCreationBadScript
  3380  )
  3381  
  3382  // newChannelEdgeInfo is a helper function used to create a new channel edge,
  3383  // possibly skipping adding it to parts of the chain/state as well.
  3384  func newChannelEdgeInfo(ctx *testCtx, fundingHeight uint32,
  3385  	ecm edgeCreationModifier) (*channeldb.ChannelEdgeInfo, error) {
  3386  
  3387  	node1, err := createTestNode()
  3388  	if err != nil {
  3389  		return nil, err
  3390  	}
  3391  	node2, err := createTestNode()
  3392  	if err != nil {
  3393  		return nil, err
  3394  	}
  3395  
  3396  	fundingTx, _, chanID, err := createChannelEdge(
  3397  		ctx, bitcoinKey1.SerializeCompressed(),
  3398  		bitcoinKey2.SerializeCompressed(), 100, fundingHeight,
  3399  	)
  3400  	if err != nil {
  3401  		return nil, fmt.Errorf("unable to create edge: %w", err)
  3402  	}
  3403  
  3404  	edge := &channeldb.ChannelEdgeInfo{
  3405  		ChannelID:     chanID.ToUint64(),
  3406  		NodeKey1Bytes: node1.PubKeyBytes,
  3407  		NodeKey2Bytes: node2.PubKeyBytes,
  3408  	}
  3409  	copy(edge.DecredKey1Bytes[:], bitcoinKey1.SerializeCompressed())
  3410  	copy(edge.DecredKey2Bytes[:], bitcoinKey2.SerializeCompressed())
  3411  
  3412  	if ecm == edgeCreationNoFundingTx {
  3413  		return edge, nil
  3414  	}
  3415  
  3416  	fundingBlock := &wire.MsgBlock{
  3417  		Transactions: []*wire.MsgTx{fundingTx},
  3418  	}
  3419  	ctx.chain.addBlock(fundingBlock, chanID.BlockHeight, chanID.BlockHeight)
  3420  
  3421  	if ecm == edgeCreationNoUTXO {
  3422  		ctx.chain.delUtxo(wire.OutPoint{
  3423  			Hash: fundingTx.TxHash(),
  3424  		})
  3425  	}
  3426  
  3427  	if ecm == edgeCreationBadScript {
  3428  		fundingTx.TxOut[0].PkScript[0] ^= 1
  3429  	}
  3430  
  3431  	return edge, nil
  3432  }
  3433  
  3434  func assertChanChainRejection(t *testing.T, ctx *testCtx,
  3435  	edge *channeldb.ChannelEdgeInfo, failCode errorCode) {
  3436  
  3437  	t.Helper()
  3438  
  3439  	err := ctx.router.AddEdge(edge)
  3440  	if !IsError(err, failCode) {
  3441  		t.Fatalf("validation should have failed: %v", err)
  3442  	}
  3443  
  3444  	// This channel should now be present in the zombie channel index.
  3445  	_, _, _, isZombie, err := ctx.graph.HasChannelEdge(
  3446  		edge.ChannelID,
  3447  	)
  3448  	require.Nil(t, err)
  3449  	require.True(t, isZombie, "edge should be marked as zombie")
  3450  }
  3451  
  3452  // TestChannelOnChainRejectionZombie tests that if we fail validating a channel
  3453  // due to some sort of on-chain rejection (no funding transaction, or invalid
  3454  // UTXO), then we'll mark the channel as a zombie.
  3455  func TestChannelOnChainRejectionZombie(t *testing.T) {
  3456  	t.Parallel()
  3457  
  3458  	ctx, cleanup := createTestCtxSingleNode(t, 0)
  3459  	defer cleanup()
  3460  
  3461  	// To start,  we'll make an edge for the channel, but we won't add the
  3462  	// funding transaction to the mock blockchain, which should cause the
  3463  	// validation to fail below.
  3464  	edge, err := newChannelEdgeInfo(ctx, 1, edgeCreationNoFundingTx)
  3465  	require.Nil(t, err)
  3466  
  3467  	// We expect this to fail as the transaction isn't present in the
  3468  	// chain (nor the block).
  3469  	assertChanChainRejection(t, ctx, edge, ErrNoFundingTransaction)
  3470  
  3471  	// Next, we'll make another channel edge, but actually add it to the
  3472  	// graph this time.
  3473  	edge, err = newChannelEdgeInfo(ctx, 2, edgeCreationNoUTXO)
  3474  	require.Nil(t, err)
  3475  
  3476  	// Instead now, we'll remove it from the set of UTXOs which should
  3477  	// cause the spentness validation to fail.
  3478  	assertChanChainRejection(t, ctx, edge, ErrChannelSpent)
  3479  
  3480  	// If we cause the funding transaction the chain to fail validation, we
  3481  	// should see similar behavior.
  3482  	edge, err = newChannelEdgeInfo(ctx, 3, edgeCreationBadScript)
  3483  	require.Nil(t, err)
  3484  	assertChanChainRejection(t, ctx, edge, ErrInvalidFundingOutput)
  3485  }
  3486  
  3487  func createDummyTestGraph(t *testing.T) *testGraphInstance {
  3488  	// Setup two simple channels such that we can mock sending along this
  3489  	// route.
  3490  	chanCapSat := dcrutil.Amount(100000)
  3491  	testChannels := []*testChannel{
  3492  		symmetricTestChannel("a", "b", chanCapSat, &testChannelPolicy{
  3493  			Expiry:  144,
  3494  			FeeRate: 400,
  3495  			MinHTLC: 1,
  3496  			MaxHTLC: lnwire.NewMAtomsFromAtoms(chanCapSat),
  3497  		}, 1),
  3498  		symmetricTestChannel("b", "c", chanCapSat, &testChannelPolicy{
  3499  			Expiry:  144,
  3500  			FeeRate: 400,
  3501  			MinHTLC: 1,
  3502  			MaxHTLC: lnwire.NewMAtomsFromAtoms(chanCapSat),
  3503  		}, 2),
  3504  	}
  3505  
  3506  	testGraph, err := createTestGraphFromChannels(true, testChannels, "a")
  3507  	require.NoError(t, err, "failed to create graph")
  3508  	return testGraph
  3509  }
  3510  
  3511  func createDummyLightningPayment(t *testing.T,
  3512  	target route.Vertex, amt lnwire.MilliAtom) *LightningPayment {
  3513  
  3514  	var preImage lntypes.Preimage
  3515  	_, err := rand.Read(preImage[:])
  3516  	require.NoError(t, err, "unable to generate preimage")
  3517  
  3518  	payHash := preImage.Hash()
  3519  
  3520  	return &LightningPayment{
  3521  		Target:      target,
  3522  		Amount:      amt,
  3523  		FeeLimit:    noFeeLimit,
  3524  		paymentHash: &payHash,
  3525  	}
  3526  }
  3527  
  3528  // TestSendMPPaymentSucceed tests that we can successfully send a MPPayment via
  3529  // router.SendPayment. This test mainly focuses on testing the logic of the
  3530  // method resumePayment is implemented as expected.
  3531  func TestSendMPPaymentSucceed(t *testing.T) {
  3532  	const startingBlockHeight = 101
  3533  
  3534  	// Create mockers to initialize the router.
  3535  	controlTower := &mockControlTower{}
  3536  	sessionSource := &mockPaymentSessionSource{}
  3537  	missionControl := &mockMissionControl{}
  3538  	payer := &mockPaymentAttemptDispatcher{}
  3539  	chain := newMockChain(startingBlockHeight)
  3540  	chainView := newMockChainView(chain)
  3541  	testGraph := createDummyTestGraph(t)
  3542  
  3543  	// Define the behavior of the mockers to the point where we can
  3544  	// successfully start the router.
  3545  	controlTower.On("FetchInFlightPayments").Return(
  3546  		[]*channeldb.MPPayment{}, nil,
  3547  	)
  3548  	payer.On("CleanStore", mock.Anything).Return(nil)
  3549  
  3550  	// Create and start the router.
  3551  	router, err := New(Config{
  3552  		Control:        controlTower,
  3553  		SessionSource:  sessionSource,
  3554  		MissionControl: missionControl,
  3555  		Payer:          payer,
  3556  
  3557  		// TODO(yy): create new mocks for the chain and chainview.
  3558  		Chain:     chain,
  3559  		ChainView: chainView,
  3560  
  3561  		// TODO(yy): mock the graph once it's changed into interface.
  3562  		Graph: testGraph.graph,
  3563  
  3564  		Clock:              clock.NewTestClock(time.Unix(1, 0)),
  3565  		GraphPruneInterval: time.Hour * 2,
  3566  		NextPaymentID: func() (uint64, error) {
  3567  			next := atomic.AddUint64(&uniquePaymentID, 1)
  3568  			return next, nil
  3569  		},
  3570  	})
  3571  	require.NoError(t, err, "failed to create router")
  3572  
  3573  	// Make sure the router can start and stop without error.
  3574  	require.NoError(t, router.Start(), "router failed to start")
  3575  	defer func() {
  3576  		require.NoError(t, router.Stop(), "router failed to stop")
  3577  	}()
  3578  
  3579  	// Once the router is started, check that the mocked methods are called
  3580  	// as expected.
  3581  	controlTower.AssertExpectations(t)
  3582  	payer.AssertExpectations(t)
  3583  
  3584  	// Mock the methods to the point where we are inside the function
  3585  	// resumePayment.
  3586  	paymentAmt := lnwire.MilliAtom(10000)
  3587  	req := createDummyLightningPayment(
  3588  		t, testGraph.aliasMap["c"], paymentAmt,
  3589  	)
  3590  	identifier := lntypes.Hash(req.Identifier())
  3591  	session := &mockPaymentSession{}
  3592  	sessionSource.On("NewPaymentSession", req).Return(session, nil)
  3593  	controlTower.On("InitPayment", identifier, mock.Anything).Return(nil)
  3594  
  3595  	// The following mocked methods are called inside resumePayment. Note
  3596  	// that the payment object below will determine the state of the
  3597  	// paymentLifecycle.
  3598  	payment := &channeldb.MPPayment{}
  3599  	controlTower.On("FetchPayment", identifier).Return(payment, nil)
  3600  
  3601  	// Create a route that can send 1/4 of the total amount. This value
  3602  	// will be returned by calling RequestRoute.
  3603  	shard, err := createTestRoute(paymentAmt/4, testGraph.aliasMap)
  3604  	require.NoError(t, err, "failed to create route")
  3605  	session.On("RequestRoute",
  3606  		mock.Anything, mock.Anything, mock.Anything, mock.Anything,
  3607  	).Return(shard, nil)
  3608  
  3609  	// Make a new htlc attempt with zero fee and append it to the payment's
  3610  	// HTLCs when calling RegisterAttempt.
  3611  	activeAttempt := makeActiveAttempt(int(paymentAmt/4), 0)
  3612  	controlTower.On("RegisterAttempt",
  3613  		identifier, mock.Anything,
  3614  	).Return(nil).Run(func(args mock.Arguments) {
  3615  		payment.HTLCs = append(payment.HTLCs, activeAttempt)
  3616  	})
  3617  
  3618  	// Create a buffered chan and it will be returned by GetPaymentResult.
  3619  	payer.resultChan = make(chan *htlcswitch.PaymentResult, 10)
  3620  	payer.On("GetPaymentResult",
  3621  		mock.Anything, identifier, mock.Anything,
  3622  	).Run(func(args mock.Arguments) {
  3623  		// Before the mock method is returned, we send the result to
  3624  		// the read-only chan.
  3625  		payer.resultChan <- &htlcswitch.PaymentResult{}
  3626  	})
  3627  
  3628  	// Simple mocking the rest.
  3629  	payer.On("SendHTLC",
  3630  		mock.Anything, mock.Anything, mock.Anything,
  3631  	).Return(nil)
  3632  	missionControl.On("ReportPaymentSuccess",
  3633  		mock.Anything, mock.Anything,
  3634  	).Return(nil)
  3635  
  3636  	// Mock SettleAttempt by changing one of the HTLCs to be settled.
  3637  	preimage := lntypes.Preimage{1, 2, 3}
  3638  	settledAttempt := makeSettledAttempt(
  3639  		int(paymentAmt/4), 0, preimage,
  3640  	)
  3641  	controlTower.On("SettleAttempt",
  3642  		identifier, mock.Anything, mock.Anything,
  3643  	).Return(&settledAttempt, nil).Run(func(args mock.Arguments) {
  3644  		// Whenever this method is invoked, we will mark the first
  3645  		// active attempt settled and exit.
  3646  		for i, attempt := range payment.HTLCs {
  3647  			if attempt.Settle == nil {
  3648  				attempt.Settle = &channeldb.HTLCSettleInfo{
  3649  					Preimage: preimage,
  3650  				}
  3651  				payment.HTLCs[i] = attempt
  3652  				return
  3653  			}
  3654  		}
  3655  	})
  3656  
  3657  	// Call the actual method SendPayment on router. This is place inside a
  3658  	// goroutine so we can set a timeout for the whole test, in case
  3659  	// anything goes wrong and the test never finishes.
  3660  	done := make(chan struct{})
  3661  	var p lntypes.Hash
  3662  	go func() {
  3663  		p, _, err = router.SendPayment(req)
  3664  		close(done)
  3665  	}()
  3666  
  3667  	select {
  3668  	case <-done:
  3669  	case <-time.After(testTimeout):
  3670  		t.Fatalf("SendPayment didn't exit")
  3671  	}
  3672  
  3673  	// Finally, validate the returned values and check that the mock
  3674  	// methods are called as expected.
  3675  	require.NoError(t, err, "send payment failed")
  3676  	require.EqualValues(t, preimage, p, "preimage not match")
  3677  
  3678  	// Note that we also implicitly check the methods such as FailAttempt,
  3679  	// ReportPaymentFail, etc, are not called because we never mocked them
  3680  	// in this test. If any of the unexpected methods was called, the test
  3681  	// would fail.
  3682  	controlTower.AssertExpectations(t)
  3683  	payer.AssertExpectations(t)
  3684  	sessionSource.AssertExpectations(t)
  3685  	session.AssertExpectations(t)
  3686  	missionControl.AssertExpectations(t)
  3687  }
  3688  
  3689  // TestSendMPPaymentSucceedOnExtraShards tests that we need extra attempts if
  3690  // there are failed ones,so that a payment is successfully sent. This test
  3691  // mainly focuses on testing the logic of the method resumePayment is
  3692  // implemented as expected.
  3693  func TestSendMPPaymentSucceedOnExtraShards(t *testing.T) {
  3694  	const startingBlockHeight = 101
  3695  
  3696  	// Create mockers to initialize the router.
  3697  	controlTower := &mockControlTower{}
  3698  	sessionSource := &mockPaymentSessionSource{}
  3699  	missionControl := &mockMissionControl{}
  3700  	payer := &mockPaymentAttemptDispatcher{}
  3701  	chain := newMockChain(startingBlockHeight)
  3702  	chainView := newMockChainView(chain)
  3703  	testGraph := createDummyTestGraph(t)
  3704  
  3705  	// Define the behavior of the mockers to the point where we can
  3706  	// successfully start the router.
  3707  	controlTower.On("FetchInFlightPayments").Return(
  3708  		[]*channeldb.MPPayment{}, nil,
  3709  	)
  3710  	payer.On("CleanStore", mock.Anything).Return(nil)
  3711  
  3712  	// Create and start the router.
  3713  	router, err := New(Config{
  3714  		Control:        controlTower,
  3715  		SessionSource:  sessionSource,
  3716  		MissionControl: missionControl,
  3717  		Payer:          payer,
  3718  
  3719  		// TODO(yy): create new mocks for the chain and chainview.
  3720  		Chain:     chain,
  3721  		ChainView: chainView,
  3722  
  3723  		// TODO(yy): mock the graph once it's changed into interface.
  3724  		Graph: testGraph.graph,
  3725  
  3726  		Clock:              clock.NewTestClock(time.Unix(1, 0)),
  3727  		GraphPruneInterval: time.Hour * 2,
  3728  		NextPaymentID: func() (uint64, error) {
  3729  			next := atomic.AddUint64(&uniquePaymentID, 1)
  3730  			return next, nil
  3731  		},
  3732  	})
  3733  	require.NoError(t, err, "failed to create router")
  3734  
  3735  	// Make sure the router can start and stop without error.
  3736  	require.NoError(t, router.Start(), "router failed to start")
  3737  	defer func() {
  3738  		require.NoError(t, router.Stop(), "router failed to stop")
  3739  	}()
  3740  
  3741  	// Once the router is started, check that the mocked methods are called
  3742  	// as expected.
  3743  	controlTower.AssertExpectations(t)
  3744  	payer.AssertExpectations(t)
  3745  
  3746  	// Mock the methods to the point where we are inside the function
  3747  	// resumePayment.
  3748  	paymentAmt := lnwire.MilliAtom(20000)
  3749  	req := createDummyLightningPayment(
  3750  		t, testGraph.aliasMap["c"], paymentAmt,
  3751  	)
  3752  	identifier := lntypes.Hash(req.Identifier())
  3753  	session := &mockPaymentSession{}
  3754  	sessionSource.On("NewPaymentSession", req).Return(session, nil)
  3755  	controlTower.On("InitPayment", identifier, mock.Anything).Return(nil)
  3756  
  3757  	// The following mocked methods are called inside resumePayment. Note
  3758  	// that the payment object below will determine the state of the
  3759  	// paymentLifecycle.
  3760  	payment := &channeldb.MPPayment{}
  3761  	controlTower.On("FetchPayment", identifier).Return(payment, nil)
  3762  
  3763  	// Create a route that can send 1/4 of the total amount. This value
  3764  	// will be returned by calling RequestRoute.
  3765  	shard, err := createTestRoute(paymentAmt/4, testGraph.aliasMap)
  3766  	require.NoError(t, err, "failed to create route")
  3767  	session.On("RequestRoute",
  3768  		mock.Anything, mock.Anything, mock.Anything, mock.Anything,
  3769  	).Return(shard, nil)
  3770  
  3771  	// Make a new htlc attempt with zero fee and append it to the payment's
  3772  	// HTLCs when calling RegisterAttempt.
  3773  	activeAttempt := makeActiveAttempt(int(paymentAmt/4), 0)
  3774  	controlTower.On("RegisterAttempt",
  3775  		identifier, mock.Anything,
  3776  	).Return(nil).Run(func(args mock.Arguments) {
  3777  		payment.HTLCs = append(payment.HTLCs, activeAttempt)
  3778  	})
  3779  
  3780  	// Create a buffered chan and it will be returned by GetPaymentResult.
  3781  	payer.resultChan = make(chan *htlcswitch.PaymentResult, 10)
  3782  
  3783  	// We use the failAttemptCount to track how many attempts we want to
  3784  	// fail. Each time the following mock method is called, the count gets
  3785  	// updated.
  3786  	failAttemptCount := 0
  3787  	payer.On("GetPaymentResult",
  3788  		mock.Anything, identifier, mock.Anything,
  3789  	).Run(func(args mock.Arguments) {
  3790  		// Before the mock method is returned, we send the result to
  3791  		// the read-only chan.
  3792  
  3793  		// Update the counter.
  3794  		failAttemptCount++
  3795  
  3796  		// We will make the first two attempts failed with temporary
  3797  		// error.
  3798  		if failAttemptCount <= 2 {
  3799  			payer.resultChan <- &htlcswitch.PaymentResult{
  3800  				Error: htlcswitch.NewForwardingError(
  3801  					&lnwire.FailTemporaryChannelFailure{},
  3802  					1,
  3803  				),
  3804  			}
  3805  			return
  3806  		}
  3807  
  3808  		// Otherwise we will mark the attempt succeeded.
  3809  		payer.resultChan <- &htlcswitch.PaymentResult{}
  3810  	})
  3811  
  3812  	// Mock the FailAttempt method to fail one of the attempts.
  3813  	var failedAttempt channeldb.HTLCAttempt
  3814  	controlTower.On("FailAttempt",
  3815  		identifier, mock.Anything, mock.Anything,
  3816  	).Return(&failedAttempt, nil).Run(func(args mock.Arguments) {
  3817  		// Whenever this method is invoked, we will mark the first
  3818  		// active attempt as failed and exit.
  3819  		for i, attempt := range payment.HTLCs {
  3820  			if attempt.Settle != nil || attempt.Failure != nil {
  3821  				continue
  3822  			}
  3823  
  3824  			attempt.Failure = &channeldb.HTLCFailInfo{}
  3825  			failedAttempt = attempt
  3826  			payment.HTLCs[i] = attempt
  3827  			return
  3828  		}
  3829  
  3830  	})
  3831  
  3832  	// Setup ReportPaymentFail to return nil reason and error so the
  3833  	// payment won't fail.
  3834  	missionControl.On("ReportPaymentFail",
  3835  		mock.Anything, mock.Anything, mock.Anything, mock.Anything,
  3836  	).Return(nil, nil)
  3837  
  3838  	// Simple mocking the rest.
  3839  	payer.On("SendHTLC",
  3840  		mock.Anything, mock.Anything, mock.Anything,
  3841  	).Return(nil)
  3842  	missionControl.On("ReportPaymentSuccess",
  3843  		mock.Anything, mock.Anything,
  3844  	).Return(nil)
  3845  
  3846  	// Mock SettleAttempt by changing one of the HTLCs to be settled.
  3847  	preimage := lntypes.Preimage{1, 2, 3}
  3848  	settledAttempt := makeSettledAttempt(
  3849  		int(paymentAmt/4), 0, preimage,
  3850  	)
  3851  	controlTower.On("SettleAttempt",
  3852  		identifier, mock.Anything, mock.Anything,
  3853  	).Return(&settledAttempt, nil).Run(func(args mock.Arguments) {
  3854  		// Whenever this method is invoked, we will mark the first
  3855  		// active attempt settled and exit.
  3856  		for i, attempt := range payment.HTLCs {
  3857  			if attempt.Settle != nil || attempt.Failure != nil {
  3858  				continue
  3859  			}
  3860  
  3861  			attempt.Settle = &channeldb.HTLCSettleInfo{
  3862  				Preimage: preimage,
  3863  			}
  3864  			payment.HTLCs[i] = attempt
  3865  			return
  3866  		}
  3867  	})
  3868  
  3869  	// Call the actual method SendPayment on router. This is place inside a
  3870  	// goroutine so we can set a timeout for the whole test, in case
  3871  	// anything goes wrong and the test never finishes.
  3872  	done := make(chan struct{})
  3873  	var p lntypes.Hash
  3874  	go func() {
  3875  		p, _, err = router.SendPayment(req)
  3876  		close(done)
  3877  	}()
  3878  
  3879  	select {
  3880  	case <-done:
  3881  	case <-time.After(testTimeout):
  3882  		t.Fatalf("SendPayment didn't exit")
  3883  	}
  3884  
  3885  	// Finally, validate the returned values and check that the mock
  3886  	// methods are called as expected.
  3887  	require.NoError(t, err, "send payment failed")
  3888  	require.EqualValues(t, preimage, p, "preimage not match")
  3889  
  3890  	controlTower.AssertExpectations(t)
  3891  	payer.AssertExpectations(t)
  3892  	sessionSource.AssertExpectations(t)
  3893  	session.AssertExpectations(t)
  3894  	missionControl.AssertExpectations(t)
  3895  }
  3896  
  3897  // TestSendMPPaymentFailed tests that when one of the shard fails with a
  3898  // terminal error, the router will stop attempting and the payment will fail.
  3899  // This test mainly focuses on testing the logic of the method resumePayment
  3900  // is implemented as expected.
  3901  func TestSendMPPaymentFailed(t *testing.T) {
  3902  	const startingBlockHeight = 101
  3903  
  3904  	// Create mockers to initialize the router.
  3905  	controlTower := &mockControlTower{}
  3906  	sessionSource := &mockPaymentSessionSource{}
  3907  	missionControl := &mockMissionControl{}
  3908  	payer := &mockPaymentAttemptDispatcher{}
  3909  	chain := newMockChain(startingBlockHeight)
  3910  	chainView := newMockChainView(chain)
  3911  	testGraph := createDummyTestGraph(t)
  3912  
  3913  	// Define the behavior of the mockers to the point where we can
  3914  	// successfully start the router.
  3915  	controlTower.On("FetchInFlightPayments").Return(
  3916  		[]*channeldb.MPPayment{}, nil,
  3917  	)
  3918  	payer.On("CleanStore", mock.Anything).Return(nil)
  3919  
  3920  	// Create and start the router.
  3921  	router, err := New(Config{
  3922  		Control:        controlTower,
  3923  		SessionSource:  sessionSource,
  3924  		MissionControl: missionControl,
  3925  		Payer:          payer,
  3926  
  3927  		// TODO(yy): create new mocks for the chain and chainview.
  3928  		Chain:     chain,
  3929  		ChainView: chainView,
  3930  
  3931  		// TODO(yy): mock the graph once it's changed into interface.
  3932  		Graph: testGraph.graph,
  3933  
  3934  		Clock:              clock.NewTestClock(time.Unix(1, 0)),
  3935  		GraphPruneInterval: time.Hour * 2,
  3936  		NextPaymentID: func() (uint64, error) {
  3937  			next := atomic.AddUint64(&uniquePaymentID, 1)
  3938  			return next, nil
  3939  		},
  3940  	})
  3941  	require.NoError(t, err, "failed to create router")
  3942  
  3943  	// Make sure the router can start and stop without error.
  3944  	require.NoError(t, router.Start(), "router failed to start")
  3945  	defer func() {
  3946  		require.NoError(t, router.Stop(), "router failed to stop")
  3947  	}()
  3948  
  3949  	// Once the router is started, check that the mocked methods are called
  3950  	// as expected.
  3951  	controlTower.AssertExpectations(t)
  3952  	payer.AssertExpectations(t)
  3953  
  3954  	// Mock the methods to the point where we are inside the function
  3955  	// resumePayment.
  3956  	paymentAmt := lnwire.MilliAtom(10000)
  3957  	req := createDummyLightningPayment(
  3958  		t, testGraph.aliasMap["c"], paymentAmt,
  3959  	)
  3960  	identifier := lntypes.Hash(req.Identifier())
  3961  	session := &mockPaymentSession{}
  3962  	sessionSource.On("NewPaymentSession", req).Return(session, nil)
  3963  	controlTower.On("InitPayment", identifier, mock.Anything).Return(nil)
  3964  
  3965  	// The following mocked methods are called inside resumePayment. Note
  3966  	// that the payment object below will determine the state of the
  3967  	// paymentLifecycle.
  3968  	payment := &channeldb.MPPayment{}
  3969  	controlTower.On("FetchPayment", identifier).Return(payment, nil)
  3970  
  3971  	// Create a route that can send 1/4 of the total amount. This value
  3972  	// will be returned by calling RequestRoute.
  3973  	shard, err := createTestRoute(paymentAmt/4, testGraph.aliasMap)
  3974  	require.NoError(t, err, "failed to create route")
  3975  	session.On("RequestRoute",
  3976  		mock.Anything, mock.Anything, mock.Anything, mock.Anything,
  3977  	).Return(shard, nil)
  3978  
  3979  	// Make a new htlc attempt with zero fee and append it to the payment's
  3980  	// HTLCs when calling RegisterAttempt.
  3981  	activeAttempt := makeActiveAttempt(int(paymentAmt/4), 0)
  3982  	controlTower.On("RegisterAttempt",
  3983  		identifier, mock.Anything,
  3984  	).Return(nil).Run(func(args mock.Arguments) {
  3985  		payment.HTLCs = append(payment.HTLCs, activeAttempt)
  3986  	})
  3987  
  3988  	// Create a buffered chan and it will be returned by GetPaymentResult.
  3989  	payer.resultChan = make(chan *htlcswitch.PaymentResult, 10)
  3990  
  3991  	// We use the failAttemptCount to track how many attempts we want to
  3992  	// fail. Each time the following mock method is called, the count gets
  3993  	// updated.
  3994  	failAttemptCount := 0
  3995  	payer.On("GetPaymentResult",
  3996  		mock.Anything, identifier, mock.Anything,
  3997  	).Run(func(args mock.Arguments) {
  3998  		// Before the mock method is returned, we send the result to
  3999  		// the read-only chan.
  4000  
  4001  		// Update the counter.
  4002  		failAttemptCount++
  4003  
  4004  		// We fail the first attempt with terminal error.
  4005  		if failAttemptCount == 1 {
  4006  			payer.resultChan <- &htlcswitch.PaymentResult{
  4007  				Error: htlcswitch.NewForwardingError(
  4008  					&lnwire.FailIncorrectDetails{},
  4009  					1,
  4010  				),
  4011  			}
  4012  			return
  4013  
  4014  		}
  4015  
  4016  		// We will make the rest attempts failed with temporary error.
  4017  		payer.resultChan <- &htlcswitch.PaymentResult{
  4018  			Error: htlcswitch.NewForwardingError(
  4019  				&lnwire.FailTemporaryChannelFailure{},
  4020  				1,
  4021  			),
  4022  		}
  4023  	})
  4024  
  4025  	// Mock the FailAttempt method to fail one of the attempts.
  4026  	var failedAttempt channeldb.HTLCAttempt
  4027  	controlTower.On("FailAttempt",
  4028  		identifier, mock.Anything, mock.Anything,
  4029  	).Return(&failedAttempt, nil).Run(func(args mock.Arguments) {
  4030  		// Whenever this method is invoked, we will mark the first
  4031  		// active attempt as failed and exit.
  4032  		for i, attempt := range payment.HTLCs {
  4033  			if attempt.Settle != nil || attempt.Failure != nil {
  4034  				continue
  4035  			}
  4036  
  4037  			attempt.Failure = &channeldb.HTLCFailInfo{}
  4038  			failedAttempt = attempt
  4039  			payment.HTLCs[i] = attempt
  4040  			return
  4041  		}
  4042  
  4043  	})
  4044  
  4045  	// Setup ReportPaymentFail to return nil reason and error so the
  4046  	// payment won't fail.
  4047  	var called bool
  4048  	failureReason := channeldb.FailureReasonPaymentDetails
  4049  	missionControl.On("ReportPaymentFail",
  4050  		mock.Anything, mock.Anything, mock.Anything, mock.Anything,
  4051  	).Return(&failureReason, nil).Run(func(args mock.Arguments) {
  4052  		// We only return the terminal error once, thus when the method
  4053  		// is called, we will return it with a nil error.
  4054  		if called {
  4055  			args[0] = nil
  4056  			return
  4057  		}
  4058  
  4059  		// If it's the first time calling this method, we will return a
  4060  		// terminal error.
  4061  		payment.FailureReason = &failureReason
  4062  		called = true
  4063  	})
  4064  
  4065  	// Simple mocking the rest.
  4066  	controlTower.On("Fail", identifier, failureReason).Return(nil)
  4067  	payer.On("SendHTLC",
  4068  		mock.Anything, mock.Anything, mock.Anything,
  4069  	).Return(nil)
  4070  
  4071  	// Call the actual method SendPayment on router. This is place inside a
  4072  	// goroutine so we can set a timeout for the whole test, in case
  4073  	// anything goes wrong and the test never finishes.
  4074  	done := make(chan struct{})
  4075  	var p lntypes.Hash
  4076  	go func() {
  4077  		p, _, err = router.SendPayment(req)
  4078  		close(done)
  4079  	}()
  4080  
  4081  	select {
  4082  	case <-done:
  4083  	case <-time.After(testTimeout):
  4084  		t.Fatalf("SendPayment didn't exit")
  4085  	}
  4086  
  4087  	// Finally, validate the returned values and check that the mock
  4088  	// methods are called as expected.
  4089  	require.Error(t, err, "expected send payment error")
  4090  	require.EqualValues(t, [32]byte{}, p, "preimage not match")
  4091  
  4092  	controlTower.AssertExpectations(t)
  4093  	payer.AssertExpectations(t)
  4094  	sessionSource.AssertExpectations(t)
  4095  	session.AssertExpectations(t)
  4096  	missionControl.AssertExpectations(t)
  4097  }
  4098  
  4099  // TestSendMPPaymentFailedWithShardsInFlight tests that when the payment is in
  4100  // terminal state, even if we have shards in flight, we still fail the payment
  4101  // and exit. This test mainly focuses on testing the logic of the method
  4102  // resumePayment is implemented as expected.
  4103  func TestSendMPPaymentFailedWithShardsInFlight(t *testing.T) {
  4104  	const startingBlockHeight = 101
  4105  
  4106  	// Create mockers to initialize the router.
  4107  	controlTower := &mockControlTower{}
  4108  	sessionSource := &mockPaymentSessionSource{}
  4109  	missionControl := &mockMissionControl{}
  4110  	payer := &mockPaymentAttemptDispatcher{}
  4111  	chain := newMockChain(startingBlockHeight)
  4112  	chainView := newMockChainView(chain)
  4113  	testGraph := createDummyTestGraph(t)
  4114  
  4115  	// Define the behavior of the mockers to the point where we can
  4116  	// successfully start the router.
  4117  	controlTower.On("FetchInFlightPayments").Return(
  4118  		[]*channeldb.MPPayment{}, nil,
  4119  	)
  4120  	payer.On("CleanStore", mock.Anything).Return(nil)
  4121  
  4122  	// Create and start the router.
  4123  	router, err := New(Config{
  4124  		Control:        controlTower,
  4125  		SessionSource:  sessionSource,
  4126  		MissionControl: missionControl,
  4127  		Payer:          payer,
  4128  
  4129  		// TODO(yy): create new mocks for the chain and chainview.
  4130  		Chain:     chain,
  4131  		ChainView: chainView,
  4132  
  4133  		// TODO(yy): mock the graph once it's changed into interface.
  4134  		Graph: testGraph.graph,
  4135  
  4136  		Clock:              clock.NewTestClock(time.Unix(1, 0)),
  4137  		GraphPruneInterval: time.Hour * 2,
  4138  		NextPaymentID: func() (uint64, error) {
  4139  			next := atomic.AddUint64(&uniquePaymentID, 1)
  4140  			return next, nil
  4141  		},
  4142  	})
  4143  	require.NoError(t, err, "failed to create router")
  4144  
  4145  	// Make sure the router can start and stop without error.
  4146  	require.NoError(t, router.Start(), "router failed to start")
  4147  	defer func() {
  4148  		require.NoError(t, router.Stop(), "router failed to stop")
  4149  	}()
  4150  
  4151  	// Once the router is started, check that the mocked methods are called
  4152  	// as expected.
  4153  	controlTower.AssertExpectations(t)
  4154  	payer.AssertExpectations(t)
  4155  
  4156  	// Mock the methods to the point where we are inside the function
  4157  	// resumePayment.
  4158  	paymentAmt := lnwire.MilliAtom(10000)
  4159  	req := createDummyLightningPayment(
  4160  		t, testGraph.aliasMap["c"], paymentAmt,
  4161  	)
  4162  	identifier := lntypes.Hash(req.Identifier())
  4163  	session := &mockPaymentSession{}
  4164  	sessionSource.On("NewPaymentSession", req).Return(session, nil)
  4165  	controlTower.On("InitPayment", identifier, mock.Anything).Return(nil)
  4166  
  4167  	// The following mocked methods are called inside resumePayment. Note
  4168  	// that the payment object below will determine the state of the
  4169  	// paymentLifecycle.
  4170  	payment := &channeldb.MPPayment{}
  4171  	controlTower.On("FetchPayment", identifier).Return(payment, nil)
  4172  
  4173  	// Create a route that can send 1/4 of the total amount. This value
  4174  	// will be returned by calling RequestRoute.
  4175  	shard, err := createTestRoute(paymentAmt/4, testGraph.aliasMap)
  4176  	require.NoError(t, err, "failed to create route")
  4177  	session.On("RequestRoute",
  4178  		mock.Anything, mock.Anything, mock.Anything, mock.Anything,
  4179  	).Return(shard, nil)
  4180  
  4181  	// Make a new htlc attempt with zero fee and append it to the payment's
  4182  	// HTLCs when calling RegisterAttempt.
  4183  	activeAttempt := makeActiveAttempt(int(paymentAmt/4), 0)
  4184  	controlTower.On("RegisterAttempt",
  4185  		identifier, mock.Anything,
  4186  	).Return(nil).Run(func(args mock.Arguments) {
  4187  		payment.HTLCs = append(payment.HTLCs, activeAttempt)
  4188  	})
  4189  
  4190  	// Create a buffered chan and it will be returned by GetPaymentResult.
  4191  	payer.resultChan = make(chan *htlcswitch.PaymentResult, 10)
  4192  
  4193  	// We use the getPaymentResultCnt to track how many times we called
  4194  	// GetPaymentResult. As shard launch is sequential, and we fail the
  4195  	// first shard that calls GetPaymentResult, we may end up with different
  4196  	// counts since the lifecycle itself is asynchronous. To avoid flakes
  4197  	// due to this undeterminsitic behavior, we'll compare the final
  4198  	// getPaymentResultCnt with other counters to create a final test
  4199  	// expectation.
  4200  	getPaymentResultCnt := 0
  4201  	payer.On("GetPaymentResult",
  4202  		mock.Anything, identifier, mock.Anything,
  4203  	).Run(func(args mock.Arguments) {
  4204  		// Before the mock method is returned, we send the result to
  4205  		// the read-only chan.
  4206  
  4207  		// Update the counter.
  4208  		getPaymentResultCnt++
  4209  
  4210  		// We fail the first attempt with terminal error.
  4211  		if getPaymentResultCnt == 1 {
  4212  			payer.resultChan <- &htlcswitch.PaymentResult{
  4213  				Error: htlcswitch.NewForwardingError(
  4214  					&lnwire.FailIncorrectDetails{},
  4215  					1,
  4216  				),
  4217  			}
  4218  			return
  4219  		}
  4220  
  4221  		// For the rest of the attempts we'll simulate that a network
  4222  		// result update_fail_htlc has been received. This way the
  4223  		// payment will fail cleanly.
  4224  		payer.resultChan <- &htlcswitch.PaymentResult{
  4225  			Error: htlcswitch.NewForwardingError(
  4226  				&lnwire.FailTemporaryChannelFailure{},
  4227  				1,
  4228  			),
  4229  		}
  4230  	})
  4231  
  4232  	// Mock the FailAttempt method to fail (at least once).
  4233  	var failedAttempt channeldb.HTLCAttempt
  4234  	controlTower.On("FailAttempt",
  4235  		identifier, mock.Anything, mock.Anything,
  4236  	).Return(&failedAttempt, nil).Run(func(args mock.Arguments) {
  4237  		// Whenever this method is invoked, we will mark the first
  4238  		// active attempt as failed and exit.
  4239  		failedAttempt = payment.HTLCs[0]
  4240  		failedAttempt.Failure = &channeldb.HTLCFailInfo{}
  4241  		payment.HTLCs[0] = failedAttempt
  4242  	})
  4243  
  4244  	// Setup ReportPaymentFail to return nil reason and error so the
  4245  	// payment won't fail.
  4246  	failureReason := channeldb.FailureReasonPaymentDetails
  4247  	cntReportPaymentFail := 0
  4248  	missionControl.On("ReportPaymentFail",
  4249  		mock.Anything, mock.Anything, mock.Anything, mock.Anything,
  4250  	).Return(&failureReason, nil).Run(func(args mock.Arguments) {
  4251  		payment.FailureReason = &failureReason
  4252  		cntReportPaymentFail++
  4253  	})
  4254  
  4255  	// Simple mocking the rest.
  4256  	cntFail := 0
  4257  	controlTower.On("Fail", identifier, failureReason).Return(nil)
  4258  	payer.On("SendHTLC",
  4259  		mock.Anything, mock.Anything, mock.Anything,
  4260  	).Return(nil).Run(func(args mock.Arguments) {
  4261  		cntFail++
  4262  	})
  4263  
  4264  	// Call the actual method SendPayment on router. This is place inside a
  4265  	// goroutine so we can set a timeout for the whole test, in case
  4266  	// anything goes wrong and the test never finishes.
  4267  	done := make(chan struct{})
  4268  	var p lntypes.Hash
  4269  	go func() {
  4270  		p, _, err = router.SendPayment(req)
  4271  		close(done)
  4272  	}()
  4273  
  4274  	select {
  4275  	case <-done:
  4276  	case <-time.After(testTimeout):
  4277  		t.Fatalf("SendPayment didn't exit")
  4278  	}
  4279  
  4280  	// Finally, validate the returned values and check that the mock
  4281  	// methods are called as expected.
  4282  	require.Error(t, err, "expected send payment error")
  4283  	require.EqualValues(t, [32]byte{}, p, "preimage not match")
  4284  	require.GreaterOrEqual(t, getPaymentResultCnt, 1)
  4285  	require.Equal(t, getPaymentResultCnt, cntReportPaymentFail)
  4286  	require.Equal(t, getPaymentResultCnt, cntFail)
  4287  
  4288  	controlTower.AssertExpectations(t)
  4289  	payer.AssertExpectations(t)
  4290  	sessionSource.AssertExpectations(t)
  4291  	session.AssertExpectations(t)
  4292  	missionControl.AssertExpectations(t)
  4293  }
  4294  
  4295  // TestBlockDifferenceFix tests if when the router is behind on blocks, the
  4296  // router catches up to the best block head.
  4297  func TestBlockDifferenceFix(t *testing.T) {
  4298  	t.Parallel()
  4299  
  4300  	initialBlockHeight := uint32(0)
  4301  
  4302  	// Starting height here is set to 0, which is behind where we want to be.
  4303  	ctx, cleanup := createTestCtxSingleNode(t, initialBlockHeight)
  4304  	defer cleanup()
  4305  
  4306  	// Add initial block to our mini blockchain.
  4307  	block := &wire.MsgBlock{
  4308  		Transactions: []*wire.MsgTx{},
  4309  	}
  4310  	ctx.chain.addBlock(block, initialBlockHeight, rand.Uint32())
  4311  
  4312  	// Let's generate a new block of height 5, 5 above where our node is at.
  4313  	newBlock := &wire.MsgBlock{
  4314  		Transactions: []*wire.MsgTx{},
  4315  	}
  4316  	newBlockHeight := uint32(5)
  4317  
  4318  	blockDifference := newBlockHeight - initialBlockHeight
  4319  
  4320  	ctx.chainView.notifyBlockAck = make(chan struct{}, 1)
  4321  
  4322  	ctx.chain.addBlock(newBlock, newBlockHeight, rand.Uint32())
  4323  	ctx.chain.setBestBlock(int32(newBlockHeight))
  4324  	ctx.chainView.notifyBlock(block.BlockHash(), newBlockHeight,
  4325  		[]*wire.MsgTx{}, t)
  4326  
  4327  	<-ctx.chainView.notifyBlockAck
  4328  
  4329  	// At this point, the chain notifier should have noticed that we're
  4330  	// behind on blocks, and will send the n missing blocks that we
  4331  	// need to the client's epochs channel. Let's replicate this
  4332  	// functionality.
  4333  	for i := 0; i < int(blockDifference); i++ {
  4334  		currBlockHeight := int32(i + 1)
  4335  
  4336  		nonce := rand.Uint32()
  4337  
  4338  		newBlock := &wire.MsgBlock{
  4339  			Transactions: []*wire.MsgTx{},
  4340  			Header:       wire.BlockHeader{Nonce: nonce},
  4341  		}
  4342  		ctx.chain.addBlock(newBlock, uint32(currBlockHeight), nonce)
  4343  		currHash := newBlock.Header.BlockHash()
  4344  
  4345  		newEpoch := &chainntnfs.BlockEpoch{
  4346  			Height: currBlockHeight,
  4347  			Hash:   &currHash,
  4348  		}
  4349  
  4350  		ctx.notifier.EpochChan <- newEpoch
  4351  
  4352  		ctx.chainView.notifyBlock(currHash,
  4353  			uint32(currBlockHeight), block.Transactions, t)
  4354  
  4355  		<-ctx.chainView.notifyBlockAck
  4356  	}
  4357  
  4358  	err := wait.NoError(func() error {
  4359  		// Then router height should be updated to the latest block.
  4360  		if atomic.LoadUint32(&ctx.router.bestHeight) != newBlockHeight {
  4361  			return fmt.Errorf("height should have been updated "+
  4362  				"to %v, instead got %v", newBlockHeight,
  4363  				ctx.router.bestHeight)
  4364  		}
  4365  
  4366  		return nil
  4367  	}, testTimeout)
  4368  	if err != nil {
  4369  		t.Fatalf("block height wasn't updated: %v", err)
  4370  	}
  4371  }