github.com/decred/dcrlnd@v0.7.6/htlcswitch/circuit_test.go (about)

     1  package htlcswitch_test
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/decred/dcrd/chaincfg/v3"
    10  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    11  	"github.com/decred/dcrd/dcrutil/v4"
    12  	"github.com/decred/dcrlnd/channeldb"
    13  	"github.com/decred/dcrlnd/htlcswitch"
    14  	"github.com/decred/dcrlnd/htlcswitch/hop"
    15  	"github.com/decred/dcrlnd/keychain"
    16  	"github.com/decred/dcrlnd/lnwire"
    17  	sphinx "github.com/decred/lightning-onion/v4"
    18  )
    19  
    20  var (
    21  	hash1 = [32]byte{0x01}
    22  	hash2 = [32]byte{0x02}
    23  	hash3 = [32]byte{0x03}
    24  
    25  	// sphinxPrivKey is the private key given to freshly created sphinx
    26  	// routers.
    27  	sphinxPrivKey *secp256k1.PrivateKey
    28  
    29  	// testEphemeralKey is the ephemeral key that will be extracted to
    30  	// create onion obfuscators.
    31  	testEphemeralKey *secp256k1.PublicKey
    32  
    33  	// testExtracter is a precomputed extraction of testEphemeralKey, using
    34  	// the sphinxPrivKey.
    35  	testExtracter *hop.SphinxErrorEncrypter
    36  )
    37  
    38  func init() {
    39  	// Generate a fresh key for our sphinx router.
    40  	var err error
    41  	sphinxPrivKey, err = secp256k1.GeneratePrivateKey()
    42  	if err != nil {
    43  		panic(err)
    44  	}
    45  
    46  	// And another, whose public key will serve as the test ephemeral key.
    47  	testEphemeralPriv, err := secp256k1.GeneratePrivateKey()
    48  	if err != nil {
    49  		panic(err)
    50  	}
    51  	testEphemeralKey = testEphemeralPriv.PubKey()
    52  
    53  	// Finally, properly initialize the test extracter
    54  	initTestExtracter()
    55  }
    56  
    57  // initTestExtracter spins up a new onion processor specifically for the purpose
    58  // of generating our testExtracter, which should be derived from the
    59  // testEphemeralKey, and which randomly-generated key is used to init the sphinx
    60  // router.
    61  //
    62  // NOTE: This should be called in init(), after testEphemeralKey has been
    63  // properly initialized.
    64  func initTestExtracter() {
    65  	onionProcessor := newOnionProcessor(nil)
    66  	defer onionProcessor.Stop()
    67  
    68  	obfuscator, _ := onionProcessor.ExtractErrorEncrypter(
    69  		testEphemeralKey,
    70  	)
    71  
    72  	sphinxExtracter, ok := obfuscator.(*hop.SphinxErrorEncrypter)
    73  	if !ok {
    74  		panic("did not extract sphinx error encrypter")
    75  	}
    76  
    77  	testExtracter = sphinxExtracter
    78  
    79  	// We also set this error extracter on startup, otherwise it will be nil
    80  	// at compile-time.
    81  	halfCircuitTests[2].encrypter = testExtracter
    82  }
    83  
    84  // newOnionProcessor creates starts a new htlcswitch.OnionProcessor using a temp
    85  // db and no garbage collection.
    86  func newOnionProcessor(t *testing.T) *hop.OnionProcessor {
    87  	sphinxRouter := sphinx.NewRouter(
    88  		&keychain.PrivKeyECDH{PrivKey: sphinxPrivKey},
    89  		chaincfg.SimNetParams(),
    90  		sphinx.NewMemoryReplayLog(),
    91  	)
    92  
    93  	if err := sphinxRouter.Start(); err != nil {
    94  		t.Fatalf("unable to start sphinx router: %v", err)
    95  	}
    96  
    97  	return hop.NewOnionProcessor(sphinxRouter)
    98  }
    99  
   100  // newCircuitMap creates a new htlcswitch.CircuitMap using a temp db and a
   101  // fresh sphinx router.
   102  func newCircuitMap(t *testing.T) (*htlcswitch.CircuitMapConfig,
   103  	htlcswitch.CircuitMap) {
   104  
   105  	onionProcessor := newOnionProcessor(t)
   106  
   107  	db := makeCircuitDB(t, "")
   108  	circuitMapCfg := &htlcswitch.CircuitMapConfig{
   109  		DB:                    db,
   110  		FetchAllOpenChannels:  db.ChannelStateDB().FetchAllOpenChannels,
   111  		FetchClosedChannels:   db.ChannelStateDB().FetchClosedChannels,
   112  		ExtractErrorEncrypter: onionProcessor.ExtractErrorEncrypter,
   113  	}
   114  
   115  	circuitMap, err := htlcswitch.NewCircuitMap(circuitMapCfg)
   116  	if err != nil {
   117  		t.Fatalf("unable to create persistent circuit map: %v", err)
   118  	}
   119  
   120  	return circuitMapCfg, circuitMap
   121  }
   122  
   123  // TestCircuitMapInit is a quick check to ensure that we can start and restore
   124  // the circuit map, as this will be used extensively in this suite.
   125  func TestCircuitMapInit(t *testing.T) {
   126  	t.Parallel()
   127  
   128  	cfg, _ := newCircuitMap(t)
   129  	restartCircuitMap(t, cfg)
   130  }
   131  
   132  var halfCircuitTests = []struct {
   133  	hash      [32]byte
   134  	inValue   dcrutil.Amount
   135  	outValue  dcrutil.Amount
   136  	chanID    lnwire.ShortChannelID
   137  	htlcID    uint64
   138  	encrypter hop.ErrorEncrypter
   139  }{
   140  	{
   141  		hash:      hash1,
   142  		inValue:   0,
   143  		outValue:  1000,
   144  		chanID:    lnwire.NewShortChanIDFromInt(1),
   145  		htlcID:    1,
   146  		encrypter: nil,
   147  	},
   148  	{
   149  		hash:      hash2,
   150  		inValue:   2100,
   151  		outValue:  2000,
   152  		chanID:    lnwire.NewShortChanIDFromInt(2),
   153  		htlcID:    2,
   154  		encrypter: htlcswitch.NewMockObfuscator(),
   155  	},
   156  	{
   157  		hash:     hash3,
   158  		inValue:  10000,
   159  		outValue: 9000,
   160  		chanID:   lnwire.NewShortChanIDFromInt(3),
   161  		htlcID:   3,
   162  		// NOTE: The value of testExtracter is nil at compile-time, it
   163  		// is fully-initialized in initTestExtracter, which should
   164  		// repopulate this encrypter.
   165  		encrypter: testExtracter,
   166  	},
   167  }
   168  
   169  // TestHalfCircuitSerialization checks that the half circuits can be properly
   170  // encoded and decoded properly. A critical responsibility of this test is to
   171  // verify that the various ErrorEncrypter implementations can be properly
   172  // reconstructed from a serialized half circuit.
   173  func TestHalfCircuitSerialization(t *testing.T) {
   174  	t.Parallel()
   175  
   176  	onionProcessor := newOnionProcessor(t)
   177  
   178  	for i, test := range halfCircuitTests {
   179  		circuit := &htlcswitch.PaymentCircuit{
   180  			PaymentHash:    test.hash,
   181  			IncomingAmount: lnwire.NewMAtomsFromAtoms(test.inValue),
   182  			OutgoingAmount: lnwire.NewMAtomsFromAtoms(test.outValue),
   183  			Incoming: htlcswitch.CircuitKey{
   184  				ChanID: test.chanID,
   185  				HtlcID: test.htlcID,
   186  			},
   187  			ErrorEncrypter: test.encrypter,
   188  		}
   189  
   190  		// Write the half circuit to our buffer.
   191  		var b bytes.Buffer
   192  		if err := circuit.Encode(&b); err != nil {
   193  			t.Fatalf("unable to encode half payment circuit test=%d: %v", i, err)
   194  		}
   195  
   196  		// Then try to decode the serialized bytes.
   197  		var circuit2 htlcswitch.PaymentCircuit
   198  		circuitReader := bytes.NewReader(b.Bytes())
   199  		if err := circuit2.Decode(circuitReader); err != nil {
   200  			t.Fatalf("unable to decode half payment circuit test=%d: %v", i, err)
   201  		}
   202  
   203  		// If the error encrypter is initialized, we will need to
   204  		// reextract it from it's decoded state, as this requires an
   205  		// ECDH with the onion processor's private key. For mock error
   206  		// encrypters, this will be a NOP.
   207  		if circuit2.ErrorEncrypter != nil {
   208  			err := circuit2.ErrorEncrypter.Reextract(
   209  				onionProcessor.ExtractErrorEncrypter,
   210  			)
   211  			if err != nil {
   212  				t.Fatalf("unable to reextract sphinx error "+
   213  					"encrypter: %v", err)
   214  			}
   215  		}
   216  
   217  		// Reconstructed half circuit should match the original.
   218  		if !equalIgnoreLFD(circuit, &circuit2) {
   219  			t.Fatalf("unexpected half circuit test=%d, want %v, got %v",
   220  				i, circuit, circuit2)
   221  		}
   222  	}
   223  }
   224  
   225  func TestCircuitMapPersistence(t *testing.T) {
   226  	t.Parallel()
   227  
   228  	var (
   229  		chan1      = lnwire.NewShortChanIDFromInt(1)
   230  		chan2      = lnwire.NewShortChanIDFromInt(2)
   231  		circuitMap htlcswitch.CircuitMap
   232  		err        error
   233  	)
   234  
   235  	cfg, circuitMap := newCircuitMap(t)
   236  
   237  	circuit := circuitMap.LookupCircuit(htlcswitch.CircuitKey{
   238  		ChanID: chan1,
   239  		HtlcID: 0,
   240  	})
   241  	if circuit != nil {
   242  		t.Fatalf("LookupByHTLC returned a circuit before any were added: %v",
   243  			circuit)
   244  	}
   245  
   246  	circuit1 := &htlcswitch.PaymentCircuit{
   247  		Incoming: htlcswitch.CircuitKey{
   248  			ChanID: chan2,
   249  			HtlcID: 1,
   250  		},
   251  		PaymentHash:    hash1,
   252  		ErrorEncrypter: htlcswitch.NewMockObfuscator(),
   253  	}
   254  	if _, err := circuitMap.CommitCircuits(circuit1); err != nil {
   255  		t.Fatalf("unable to add half circuit: %v", err)
   256  	}
   257  
   258  	// Circuit map should have one circuit that has not been fully opened.
   259  	assertNumCircuitsWithHash(t, circuitMap, hash1, 0)
   260  	assertHasCircuit(t, circuitMap, circuit1)
   261  
   262  	cfg, circuitMap = restartCircuitMap(t, cfg)
   263  
   264  	assertNumCircuitsWithHash(t, circuitMap, hash1, 0)
   265  	assertHasCircuit(t, circuitMap, circuit1)
   266  
   267  	// Add multiple circuits with same destination channel but different HTLC
   268  	// IDs and payment hashes.
   269  	keystone1 := htlcswitch.Keystone{
   270  		InKey: circuit1.Incoming,
   271  		OutKey: htlcswitch.CircuitKey{
   272  			ChanID: chan1,
   273  			HtlcID: 0,
   274  		},
   275  	}
   276  	circuit1.Outgoing = &keystone1.OutKey
   277  	if err := circuitMap.OpenCircuits(keystone1); err != nil {
   278  		t.Fatalf("unable to add full circuit: %v", err)
   279  	}
   280  
   281  	// Circuit map should reflect addition of circuit1, and the change
   282  	// should survive a restart.
   283  	assertNumCircuitsWithHash(t, circuitMap, hash1, 1)
   284  	assertHasCircuit(t, circuitMap, circuit1)
   285  	assertHasKeystone(t, circuitMap, keystone1.OutKey, circuit1)
   286  
   287  	cfg, circuitMap = restartCircuitMap(t, cfg)
   288  
   289  	assertNumCircuitsWithHash(t, circuitMap, hash1, 1)
   290  	assertHasCircuit(t, circuitMap, circuit1)
   291  	assertHasKeystone(t, circuitMap, keystone1.OutKey, circuit1)
   292  
   293  	circuit2 := &htlcswitch.PaymentCircuit{
   294  		Incoming: htlcswitch.CircuitKey{
   295  			ChanID: chan2,
   296  			HtlcID: 2,
   297  		},
   298  		PaymentHash:    hash2,
   299  		ErrorEncrypter: htlcswitch.NewMockObfuscator(),
   300  	}
   301  	if _, err := circuitMap.CommitCircuits(circuit2); err != nil {
   302  		t.Fatalf("unable to add half circuit: %v", err)
   303  	}
   304  
   305  	assertHasCircuit(t, circuitMap, circuit2)
   306  
   307  	keystone2 := htlcswitch.Keystone{
   308  		InKey: circuit2.Incoming,
   309  		OutKey: htlcswitch.CircuitKey{
   310  			ChanID: chan1,
   311  			HtlcID: 1,
   312  		},
   313  	}
   314  	circuit2.Outgoing = &keystone2.OutKey
   315  	if err := circuitMap.OpenCircuits(keystone2); err != nil {
   316  		t.Fatalf("unable to add full circuit: %v", err)
   317  	}
   318  
   319  	// Should have two full circuits, one under hash1 and another under
   320  	// hash2. Both half payment circuits should have been removed when the
   321  	// full circuits were added.
   322  	assertNumCircuitsWithHash(t, circuitMap, hash1, 1)
   323  	assertHasCircuit(t, circuitMap, circuit1)
   324  	assertHasKeystone(t, circuitMap, keystone1.OutKey, circuit1)
   325  
   326  	assertNumCircuitsWithHash(t, circuitMap, hash2, 1)
   327  	assertHasCircuit(t, circuitMap, circuit2)
   328  	assertHasKeystone(t, circuitMap, keystone2.OutKey, circuit2)
   329  
   330  	assertNumCircuitsWithHash(t, circuitMap, hash3, 0)
   331  
   332  	cfg, circuitMap = restartCircuitMap(t, cfg)
   333  
   334  	assertNumCircuitsWithHash(t, circuitMap, hash1, 1)
   335  	assertHasCircuit(t, circuitMap, circuit1)
   336  	assertHasKeystone(t, circuitMap, keystone1.OutKey, circuit1)
   337  
   338  	assertNumCircuitsWithHash(t, circuitMap, hash2, 1)
   339  	assertHasCircuit(t, circuitMap, circuit2)
   340  	assertHasKeystone(t, circuitMap, keystone2.OutKey, circuit2)
   341  
   342  	assertNumCircuitsWithHash(t, circuitMap, hash3, 0)
   343  
   344  	circuit3 := &htlcswitch.PaymentCircuit{
   345  		Incoming: htlcswitch.CircuitKey{
   346  			ChanID: chan1,
   347  			HtlcID: 2,
   348  		},
   349  		PaymentHash:    hash3,
   350  		ErrorEncrypter: htlcswitch.NewMockObfuscator(),
   351  	}
   352  	if _, err := circuitMap.CommitCircuits(circuit3); err != nil {
   353  		t.Fatalf("unable to add half circuit: %v", err)
   354  	}
   355  
   356  	assertHasCircuit(t, circuitMap, circuit3)
   357  	cfg, circuitMap = restartCircuitMap(t, cfg)
   358  	assertHasCircuit(t, circuitMap, circuit3)
   359  
   360  	// Add another circuit with an already-used HTLC ID but different
   361  	// destination channel.
   362  	keystone3 := htlcswitch.Keystone{
   363  		InKey: circuit3.Incoming,
   364  		OutKey: htlcswitch.CircuitKey{
   365  			ChanID: chan2,
   366  			HtlcID: 0,
   367  		},
   368  	}
   369  	circuit3.Outgoing = &keystone3.OutKey
   370  	if err := circuitMap.OpenCircuits(keystone3); err != nil {
   371  		t.Fatalf("unable to add full circuit: %v", err)
   372  	}
   373  
   374  	// Check that all have been marked as full circuits, and that no half
   375  	// circuits are currently being tracked.
   376  	assertHasKeystone(t, circuitMap, keystone1.OutKey, circuit1)
   377  	assertHasKeystone(t, circuitMap, keystone2.OutKey, circuit2)
   378  	assertHasKeystone(t, circuitMap, keystone3.OutKey, circuit3)
   379  	cfg, circuitMap = restartCircuitMap(t, cfg)
   380  	assertHasKeystone(t, circuitMap, keystone1.OutKey, circuit1)
   381  	assertHasKeystone(t, circuitMap, keystone2.OutKey, circuit2)
   382  	assertHasKeystone(t, circuitMap, keystone3.OutKey, circuit3)
   383  
   384  	// Even though a circuit was added with chan1, HTLC ID 2 as the source,
   385  	// the lookup should go by destination channel, HTLC ID.
   386  	invalidKeystone := htlcswitch.CircuitKey{
   387  		ChanID: chan1,
   388  		HtlcID: 2,
   389  	}
   390  	circuit = circuitMap.LookupOpenCircuit(invalidKeystone)
   391  	if circuit != nil {
   392  		t.Fatalf("LookupByHTLC returned a circuit without being added: %v",
   393  			circuit)
   394  	}
   395  
   396  	circuit4 := &htlcswitch.PaymentCircuit{
   397  		Incoming: htlcswitch.CircuitKey{
   398  			ChanID: chan2,
   399  			HtlcID: 3,
   400  		},
   401  		PaymentHash:    hash1,
   402  		ErrorEncrypter: htlcswitch.NewMockObfuscator(),
   403  	}
   404  	if _, err := circuitMap.CommitCircuits(circuit4); err != nil {
   405  		t.Fatalf("unable to add half circuit: %v", err)
   406  	}
   407  
   408  	// Circuit map should still only show one circuit with hash1, since we
   409  	// have not set the keystone for circuit4.
   410  	assertNumCircuitsWithHash(t, circuitMap, hash1, 1)
   411  	assertHasCircuit(t, circuitMap, circuit4)
   412  
   413  	cfg, circuitMap = restartCircuitMap(t, cfg)
   414  
   415  	assertNumCircuitsWithHash(t, circuitMap, hash1, 1)
   416  	assertHasCircuit(t, circuitMap, circuit4)
   417  
   418  	// Add a circuit with a destination channel and payment hash that are
   419  	// already added but a different HTLC ID.
   420  	keystone4 := htlcswitch.Keystone{
   421  		InKey: circuit4.Incoming,
   422  		OutKey: htlcswitch.CircuitKey{
   423  			ChanID: chan1,
   424  			HtlcID: 3,
   425  		},
   426  	}
   427  	circuit4.Outgoing = &keystone4.OutKey
   428  	if err := circuitMap.OpenCircuits(keystone4); err != nil {
   429  		t.Fatalf("unable to add full circuit: %v", err)
   430  	}
   431  
   432  	// Verify that all circuits have been fully added.
   433  	assertHasCircuit(t, circuitMap, circuit1)
   434  	assertHasKeystone(t, circuitMap, keystone1.OutKey, circuit1)
   435  	assertHasCircuit(t, circuitMap, circuit2)
   436  	assertHasKeystone(t, circuitMap, keystone2.OutKey, circuit2)
   437  	assertHasCircuit(t, circuitMap, circuit3)
   438  	assertHasKeystone(t, circuitMap, keystone3.OutKey, circuit3)
   439  	assertHasCircuit(t, circuitMap, circuit4)
   440  	assertHasKeystone(t, circuitMap, keystone4.OutKey, circuit4)
   441  
   442  	// Verify that each circuit is exposed via the proper hash bucketing.
   443  	assertNumCircuitsWithHash(t, circuitMap, hash1, 2)
   444  	assertHasCircuitForHash(t, circuitMap, hash1, circuit1)
   445  	assertHasCircuitForHash(t, circuitMap, hash1, circuit4)
   446  
   447  	assertNumCircuitsWithHash(t, circuitMap, hash2, 1)
   448  	assertHasCircuitForHash(t, circuitMap, hash2, circuit2)
   449  
   450  	assertNumCircuitsWithHash(t, circuitMap, hash3, 1)
   451  	assertHasCircuitForHash(t, circuitMap, hash3, circuit3)
   452  
   453  	// Restart, then run checks again.
   454  	cfg, circuitMap = restartCircuitMap(t, cfg)
   455  
   456  	// Verify that all circuits have been fully added.
   457  	assertHasCircuit(t, circuitMap, circuit1)
   458  	assertHasKeystone(t, circuitMap, keystone1.OutKey, circuit1)
   459  	assertHasCircuit(t, circuitMap, circuit2)
   460  	assertHasKeystone(t, circuitMap, keystone2.OutKey, circuit2)
   461  	assertHasCircuit(t, circuitMap, circuit3)
   462  	assertHasKeystone(t, circuitMap, keystone3.OutKey, circuit3)
   463  	assertHasCircuit(t, circuitMap, circuit4)
   464  	assertHasKeystone(t, circuitMap, keystone4.OutKey, circuit4)
   465  
   466  	// Verify that each circuit is exposed via the proper hash bucketing.
   467  	assertNumCircuitsWithHash(t, circuitMap, hash1, 2)
   468  	assertHasCircuitForHash(t, circuitMap, hash1, circuit1)
   469  	assertHasCircuitForHash(t, circuitMap, hash1, circuit4)
   470  
   471  	assertNumCircuitsWithHash(t, circuitMap, hash2, 1)
   472  	assertHasCircuitForHash(t, circuitMap, hash2, circuit2)
   473  
   474  	assertNumCircuitsWithHash(t, circuitMap, hash3, 1)
   475  	assertHasCircuitForHash(t, circuitMap, hash3, circuit3)
   476  
   477  	// Test removing circuits and the subsequent lookups.
   478  	err = circuitMap.DeleteCircuits(circuit1.Incoming)
   479  	if err != nil {
   480  		t.Fatalf("Remove returned unexpected error: %v", err)
   481  	}
   482  
   483  	// There should be exactly one remaining circuit with hash1, and it
   484  	// should be circuit4.
   485  	assertNumCircuitsWithHash(t, circuitMap, hash1, 1)
   486  	assertHasCircuitForHash(t, circuitMap, hash1, circuit4)
   487  	cfg, circuitMap = restartCircuitMap(t, cfg)
   488  	assertNumCircuitsWithHash(t, circuitMap, hash1, 1)
   489  	assertHasCircuitForHash(t, circuitMap, hash1, circuit4)
   490  
   491  	// Removing already-removed circuit should return an error.
   492  	err = circuitMap.DeleteCircuits(circuit1.Incoming)
   493  	if err != nil {
   494  		t.Fatalf("Unexpected failure when deleting already "+
   495  			"deleted circuit: %v", err)
   496  	}
   497  
   498  	// Verify that nothing related to hash1 has changed
   499  	assertNumCircuitsWithHash(t, circuitMap, hash1, 1)
   500  	assertHasCircuitForHash(t, circuitMap, hash1, circuit4)
   501  
   502  	// Remove last remaining circuit with payment hash hash1.
   503  	err = circuitMap.DeleteCircuits(circuit4.Incoming)
   504  	if err != nil {
   505  		t.Fatalf("Remove returned unexpected error: %v", err)
   506  	}
   507  
   508  	assertNumCircuitsWithHash(t, circuitMap, hash1, 0)
   509  	assertNumCircuitsWithHash(t, circuitMap, hash2, 1)
   510  	assertNumCircuitsWithHash(t, circuitMap, hash3, 1)
   511  	cfg, circuitMap = restartCircuitMap(t, cfg)
   512  	assertNumCircuitsWithHash(t, circuitMap, hash1, 0)
   513  	assertNumCircuitsWithHash(t, circuitMap, hash2, 1)
   514  	assertNumCircuitsWithHash(t, circuitMap, hash3, 1)
   515  
   516  	// Remove last remaining circuit with payment hash hash2.
   517  	err = circuitMap.DeleteCircuits(circuit2.Incoming)
   518  	if err != nil {
   519  		t.Fatalf("Remove returned unexpected error: %v", err)
   520  	}
   521  
   522  	// There should now only be one remaining circuit, with hash3.
   523  	assertNumCircuitsWithHash(t, circuitMap, hash2, 0)
   524  	assertNumCircuitsWithHash(t, circuitMap, hash3, 1)
   525  	cfg, circuitMap = restartCircuitMap(t, cfg)
   526  	assertNumCircuitsWithHash(t, circuitMap, hash2, 0)
   527  	assertNumCircuitsWithHash(t, circuitMap, hash3, 1)
   528  
   529  	// In removing the final circuit, we will try and remove all other known
   530  	// circuits as well. Any circuits that are unknown to the circuit map
   531  	// will be ignored, and only circuit 3 should be cause any change in the
   532  	// state.
   533  	err = circuitMap.DeleteCircuits(
   534  		circuit1.Incoming, circuit2.Incoming,
   535  		circuit3.Incoming, circuit4.Incoming,
   536  	)
   537  	if err != nil {
   538  		t.Fatalf("Unexpected failure when removing circuit while also "+
   539  			"deleting already deleted circuits: %v", err)
   540  	}
   541  
   542  	// Check that the circuit map is empty, even after restarting.
   543  	assertNumCircuitsWithHash(t, circuitMap, hash3, 0)
   544  	_, circuitMap = restartCircuitMap(t, cfg)
   545  	assertNumCircuitsWithHash(t, circuitMap, hash3, 0)
   546  }
   547  
   548  // assertHasKeystone tests that the circuit map contains the provided payment
   549  // circuit.
   550  func assertHasKeystone(t *testing.T, cm htlcswitch.CircuitMap,
   551  	outKey htlcswitch.CircuitKey, c *htlcswitch.PaymentCircuit) {
   552  
   553  	circuit := cm.LookupOpenCircuit(outKey)
   554  	if !equalIgnoreLFD(circuit, c) {
   555  		t.Fatalf("unexpected circuit, want: %v, got %v", c, circuit)
   556  	}
   557  }
   558  
   559  // assertHasCircuitForHash tests that the provided circuit appears in the list
   560  // of circuits for the given hash.
   561  func assertHasCircuitForHash(t *testing.T, cm htlcswitch.CircuitMap, hash [32]byte,
   562  	circuit *htlcswitch.PaymentCircuit) {
   563  
   564  	circuits := cm.LookupByPaymentHash(hash)
   565  	for _, c := range circuits {
   566  		if equalIgnoreLFD(c, circuit) {
   567  			return
   568  		}
   569  	}
   570  
   571  	t.Fatalf("unable to find circuit: %v by hash: %v", circuit, hash)
   572  }
   573  
   574  // assertNumCircuitsWithHash tests that the circuit has the right number of full
   575  // circuits, indexed by the given hash.
   576  func assertNumCircuitsWithHash(t *testing.T, cm htlcswitch.CircuitMap,
   577  	hash [32]byte, expectedNum int) {
   578  
   579  	circuits := cm.LookupByPaymentHash(hash)
   580  	if len(circuits) != expectedNum {
   581  		t.Fatalf("LookupByPaymentHash returned wrong number of circuits for "+
   582  			"hash=%v: expecected %d, got %d", hash, expectedNum,
   583  			len(circuits))
   584  	}
   585  }
   586  
   587  // assertHasCircuit queries the circuit map using the half-circuit's half
   588  // key, and fails if the returned half-circuit differs from the provided one.
   589  func assertHasCircuit(t *testing.T, cm htlcswitch.CircuitMap,
   590  	c *htlcswitch.PaymentCircuit) {
   591  
   592  	c2 := cm.LookupCircuit(c.Incoming)
   593  	if !equalIgnoreLFD(c, c2) {
   594  		t.Fatalf("expected circuit: %v, got %v", c, c2)
   595  	}
   596  }
   597  
   598  // equalIgnoreLFD compares two payment circuits, but ignores the current value
   599  // of LoadedFromDisk. The value is temporarily set to false for the comparison
   600  // and then restored.
   601  func equalIgnoreLFD(c, c2 *htlcswitch.PaymentCircuit) bool {
   602  	ogLFD := c.LoadedFromDisk
   603  	ogLFD2 := c2.LoadedFromDisk
   604  
   605  	c.LoadedFromDisk = false
   606  	c2.LoadedFromDisk = false
   607  
   608  	isEqual := reflect.DeepEqual(c, c2)
   609  
   610  	c.LoadedFromDisk = ogLFD
   611  	c2.LoadedFromDisk = ogLFD2
   612  
   613  	return isEqual
   614  }
   615  
   616  // makeCircuitDB initializes a new test channeldb for testing the persistence
   617  // of the circuit map. If an empty string is provided as a path, a temp
   618  // directory will be created.
   619  func makeCircuitDB(t *testing.T, path string) *channeldb.DB {
   620  	if path == "" {
   621  		var err error
   622  		path, err = ioutil.TempDir("", "circuitdb")
   623  		if err != nil {
   624  			t.Fatalf("unable to create temp path: %v", err)
   625  		}
   626  	}
   627  
   628  	db, err := channeldb.Open(path)
   629  	if err != nil {
   630  		t.Fatalf("unable to open channel db: %v", err)
   631  	}
   632  
   633  	return db
   634  }
   635  
   636  // Creates a new circuit map, backed by a freshly opened channeldb. The existing
   637  // channeldb is closed in order to simulate a complete restart.
   638  func restartCircuitMap(t *testing.T, cfg *htlcswitch.CircuitMapConfig) (
   639  	*htlcswitch.CircuitMapConfig, htlcswitch.CircuitMap) {
   640  
   641  	// Record the current temp path and close current db. We know we have
   642  	// a full channeldb.DB here since we created it just above.
   643  	dbPath := cfg.DB.(*channeldb.DB).Path()
   644  	cfg.DB.Close()
   645  
   646  	// Reinitialize circuit map with same db path.
   647  	db := makeCircuitDB(t, dbPath)
   648  	cfg2 := &htlcswitch.CircuitMapConfig{
   649  		DB:                    db,
   650  		FetchAllOpenChannels:  db.ChannelStateDB().FetchAllOpenChannels,
   651  		FetchClosedChannels:   db.ChannelStateDB().FetchClosedChannels,
   652  		ExtractErrorEncrypter: cfg.ExtractErrorEncrypter,
   653  	}
   654  	cm2, err := htlcswitch.NewCircuitMap(cfg2)
   655  	if err != nil {
   656  		t.Fatalf("unable to recreate persistent circuit map: %v", err)
   657  	}
   658  
   659  	return cfg2, cm2
   660  }
   661  
   662  // TestCircuitMapCommitCircuits tests the following behavior of CommitCircuits:
   663  // 1. New circuits are successfully added.
   664  // 2. Duplicate circuits are dropped anytime before circuit map shutsdown.
   665  // 3. Duplicate circuits are failed anytime after circuit map restarts.
   666  func TestCircuitMapCommitCircuits(t *testing.T) {
   667  	t.Parallel()
   668  
   669  	var (
   670  		chan1      = lnwire.NewShortChanIDFromInt(1)
   671  		circuitMap htlcswitch.CircuitMap
   672  		err        error
   673  	)
   674  
   675  	cfg, circuitMap := newCircuitMap(t)
   676  
   677  	circuit := &htlcswitch.PaymentCircuit{
   678  		Incoming: htlcswitch.CircuitKey{
   679  			ChanID: chan1,
   680  			HtlcID: 3,
   681  		},
   682  		ErrorEncrypter: testExtracter,
   683  	}
   684  
   685  	// First we will try to add an new circuit to the circuit map, this
   686  	// should succeed.
   687  	actions, err := circuitMap.CommitCircuits(circuit)
   688  	if err != nil {
   689  		t.Fatalf("failed to commit circuits: %v", err)
   690  	}
   691  	if len(actions.Drops) > 0 {
   692  		t.Fatalf("new circuit should not have been dropped")
   693  	}
   694  	if len(actions.Fails) > 0 {
   695  		t.Fatalf("new circuit should not have failed")
   696  	}
   697  	if len(actions.Adds) != 1 {
   698  		t.Fatalf("only one circuit should have been added, found %d",
   699  			len(actions.Adds))
   700  	}
   701  
   702  	circuit2 := circuitMap.LookupCircuit(circuit.Incoming)
   703  	if !reflect.DeepEqual(circuit, circuit2) {
   704  		t.Fatalf("unexpected committed circuit: got %v, want %v",
   705  			circuit2, circuit)
   706  	}
   707  
   708  	// Then we will try to readd the same circuit again, this should result
   709  	// in the circuit being dropped. This can happen if the incoming link
   710  	// flaps.
   711  	actions, err = circuitMap.CommitCircuits(circuit)
   712  	if err != nil {
   713  		t.Fatalf("failed to commit circuits: %v", err)
   714  	}
   715  	if len(actions.Adds) > 0 {
   716  		t.Fatalf("duplicate circuit should not have been added to circuit map")
   717  	}
   718  	if len(actions.Fails) > 0 {
   719  		t.Fatalf("duplicate circuit should not have failed")
   720  	}
   721  	if len(actions.Drops) != 1 {
   722  		t.Fatalf("only one circuit should have been dropped, found %d",
   723  			len(actions.Drops))
   724  	}
   725  
   726  	// Finally, restart the circuit map, which will cause the added circuit
   727  	// to be loaded from disk. Since the keystone was never set, subsequent
   728  	// attempts to commit the circuit should cause the circuit map to
   729  	// indicate that the HTLC should be failed back.
   730  	_, circuitMap = restartCircuitMap(t, cfg)
   731  
   732  	actions, err = circuitMap.CommitCircuits(circuit)
   733  	if err != nil {
   734  		t.Fatalf("failed to commit circuits: %v", err)
   735  	}
   736  	if len(actions.Adds) > 0 {
   737  		t.Fatalf("duplicate circuit with incomplete forwarding " +
   738  			"decision should not have been added to circuit map")
   739  	}
   740  	if len(actions.Drops) > 0 {
   741  		t.Fatalf("duplicate circuit with incomplete forwarding " +
   742  			"decision should not have been dropped by circuit map")
   743  	}
   744  	if len(actions.Fails) != 1 {
   745  		t.Fatalf("only one duplicate circuit with incomplete "+
   746  			"forwarding decision should have been failed, found: "+
   747  			"%d", len(actions.Fails))
   748  	}
   749  
   750  	// Lookup the committed circuit again, it should be identical apart from
   751  	// the loaded from disk flag.
   752  	circuit2 = circuitMap.LookupCircuit(circuit.Incoming)
   753  	if !equalIgnoreLFD(circuit, circuit2) {
   754  		t.Fatalf("unexpected committed circuit: got %v, want %v",
   755  			circuit2, circuit)
   756  	}
   757  }
   758  
   759  // TestCircuitMapOpenCircuits checks that circuits are properly opened, and that
   760  // duplicate attempts to open a circuit will result in an error.
   761  func TestCircuitMapOpenCircuits(t *testing.T) {
   762  	t.Parallel()
   763  
   764  	var (
   765  		chan1      = lnwire.NewShortChanIDFromInt(1)
   766  		chan2      = lnwire.NewShortChanIDFromInt(2)
   767  		circuitMap htlcswitch.CircuitMap
   768  		err        error
   769  	)
   770  
   771  	cfg, circuitMap := newCircuitMap(t)
   772  
   773  	circuit := &htlcswitch.PaymentCircuit{
   774  		Incoming: htlcswitch.CircuitKey{
   775  			ChanID: chan1,
   776  			HtlcID: 3,
   777  		},
   778  		ErrorEncrypter: testExtracter,
   779  	}
   780  
   781  	// First we will try to add an new circuit to the circuit map, this
   782  	// should succeed.
   783  	_, err = circuitMap.CommitCircuits(circuit)
   784  	if err != nil {
   785  		t.Fatalf("failed to commit circuits: %v", err)
   786  	}
   787  
   788  	keystone := htlcswitch.Keystone{
   789  		InKey: circuit.Incoming,
   790  		OutKey: htlcswitch.CircuitKey{
   791  			ChanID: chan2,
   792  			HtlcID: 2,
   793  		},
   794  	}
   795  
   796  	// Open the circuit for the first time.
   797  	err = circuitMap.OpenCircuits(keystone)
   798  	if err != nil {
   799  		t.Fatalf("failed to open circuits: %v", err)
   800  	}
   801  
   802  	// Check that we can retrieve the open circuit if the circuit map before
   803  	// the circuit map is restarted.
   804  	circuit2 := circuitMap.LookupOpenCircuit(keystone.OutKey)
   805  	if !reflect.DeepEqual(circuit, circuit2) {
   806  		t.Fatalf("unexpected open circuit: got %v, want %v",
   807  			circuit2, circuit)
   808  	}
   809  
   810  	if !circuit2.HasKeystone() {
   811  		t.Fatalf("open circuit should have keystone")
   812  	}
   813  	if !reflect.DeepEqual(&keystone.OutKey, circuit2.Outgoing) {
   814  		t.Fatalf("expected open circuit to have outgoing key: %v, found %v",
   815  			&keystone.OutKey, circuit2.Outgoing)
   816  	}
   817  
   818  	// Open the circuit for a second time, which should fail due to a
   819  	// duplicate keystone
   820  	err = circuitMap.OpenCircuits(keystone)
   821  	if err != htlcswitch.ErrDuplicateKeystone {
   822  		t.Fatalf("failed to open circuits: %v", err)
   823  	}
   824  
   825  	// Then we will try to readd the same circuit again, this should result
   826  	// in the circuit being dropped. This can happen if the incoming link
   827  	// flaps OR the switch is entirely restarted and the outgoing link has
   828  	// not received a response.
   829  	actions, err := circuitMap.CommitCircuits(circuit)
   830  	if err != nil {
   831  		t.Fatalf("failed to commit circuits: %v", err)
   832  	}
   833  	if len(actions.Adds) > 0 {
   834  		t.Fatalf("duplicate circuit should not have been added to circuit map")
   835  	}
   836  	if len(actions.Fails) > 0 {
   837  		t.Fatalf("duplicate circuit should not have failed")
   838  	}
   839  	if len(actions.Drops) != 1 {
   840  		t.Fatalf("only one circuit should have been dropped, found %d",
   841  			len(actions.Drops))
   842  	}
   843  
   844  	// Now, restart the circuit map, which will cause the opened circuit to
   845  	// be loaded from disk. Since we set the keystone on this circuit, it
   846  	// should be restored as such in memory.
   847  	//
   848  	// NOTE: The channel db doesn't have any channel data, so no keystones
   849  	// will be trimmed.
   850  	_, circuitMap = restartCircuitMap(t, cfg)
   851  
   852  	// Check that we can still query for the open circuit.
   853  	circuit2 = circuitMap.LookupOpenCircuit(keystone.OutKey)
   854  	if !equalIgnoreLFD(circuit, circuit2) {
   855  		t.Fatalf("unexpected open circuit: got %v, want %v",
   856  			circuit2, circuit)
   857  	}
   858  
   859  	// Try to open the circuit again, we expect this to fail since the open
   860  	// circuit was restored.
   861  	err = circuitMap.OpenCircuits(keystone)
   862  	if err != htlcswitch.ErrDuplicateKeystone {
   863  		t.Fatalf("failed to open circuits: %v", err)
   864  	}
   865  
   866  	// Lastly, with the circuit map restarted, try one more time to recommit
   867  	// the open circuit. This should be dropped, and is expected to happen
   868  	// if the incoming link flaps OR the switch is entirely restarted and
   869  	// the outgoing link has not received a response.
   870  	actions, err = circuitMap.CommitCircuits(circuit)
   871  	if err != nil {
   872  		t.Fatalf("failed to commit circuits: %v", err)
   873  	}
   874  	if len(actions.Adds) > 0 {
   875  		t.Fatalf("duplicate circuit should not have been added to circuit map")
   876  	}
   877  	if len(actions.Fails) > 0 {
   878  		t.Fatalf("duplicate circuit should not have failed")
   879  	}
   880  	if len(actions.Drops) != 1 {
   881  		t.Fatalf("only one circuit should have been dropped, found %d",
   882  			len(actions.Drops))
   883  	}
   884  }
   885  
   886  func assertCircuitsOpenedPreRestart(t *testing.T,
   887  	circuitMap htlcswitch.CircuitMap,
   888  	circuits []*htlcswitch.PaymentCircuit,
   889  	keystones []htlcswitch.Keystone) {
   890  
   891  	for i, circuit := range circuits {
   892  		keystone := keystones[i]
   893  
   894  		openCircuit := circuitMap.LookupOpenCircuit(keystone.OutKey)
   895  		if !reflect.DeepEqual(circuit, openCircuit) {
   896  			t.Fatalf("unexpected open circuit %d: got %v, want %v",
   897  				i, openCircuit, circuit)
   898  		}
   899  
   900  		if !openCircuit.HasKeystone() {
   901  			t.Fatalf("open circuit %d should have keystone", i)
   902  		}
   903  		if !reflect.DeepEqual(&keystone.OutKey, openCircuit.Outgoing) {
   904  			t.Fatalf("expected open circuit %d to have outgoing "+
   905  				"key: %v, found %v", i,
   906  				&keystone.OutKey, openCircuit.Outgoing)
   907  		}
   908  	}
   909  }
   910  
   911  func assertCircuitsOpenedPostRestart(t *testing.T,
   912  	circuitMap htlcswitch.CircuitMap,
   913  	circuits []*htlcswitch.PaymentCircuit,
   914  	keystones []htlcswitch.Keystone) {
   915  
   916  	for i, circuit := range circuits {
   917  		keystone := keystones[i]
   918  
   919  		openCircuit := circuitMap.LookupOpenCircuit(keystone.OutKey)
   920  		if !equalIgnoreLFD(circuit, openCircuit) {
   921  			t.Fatalf("unexpected open circuit %d: got %v, want %v",
   922  				i, openCircuit, circuit)
   923  		}
   924  
   925  		if !openCircuit.HasKeystone() {
   926  			t.Fatalf("open circuit %d should have keystone", i)
   927  		}
   928  		if !reflect.DeepEqual(&keystone.OutKey, openCircuit.Outgoing) {
   929  			t.Fatalf("expected open circuit %d to have outgoing "+
   930  				"key: %v, found %v", i,
   931  				&keystone.OutKey, openCircuit.Outgoing)
   932  		}
   933  	}
   934  }
   935  
   936  func assertCircuitsNotOpenedPreRestart(t *testing.T,
   937  	circuitMap htlcswitch.CircuitMap,
   938  	circuits []*htlcswitch.PaymentCircuit,
   939  	keystones []htlcswitch.Keystone,
   940  	offset int) {
   941  
   942  	for i := range circuits {
   943  		keystone := keystones[i]
   944  
   945  		openCircuit := circuitMap.LookupOpenCircuit(keystone.OutKey)
   946  		if openCircuit != nil {
   947  			t.Fatalf("expected circuit %d not to be open",
   948  				offset+i)
   949  		}
   950  
   951  		circuit := circuitMap.LookupCircuit(keystone.InKey)
   952  		if circuit == nil {
   953  			t.Fatalf("expected to find unopened circuit %d",
   954  				offset+i)
   955  		}
   956  		if circuit.HasKeystone() {
   957  			t.Fatalf("circuit %d should not have keystone",
   958  				offset+i)
   959  		}
   960  	}
   961  }
   962  
   963  // TestCircuitMapTrimOpenCircuits verifies that the circuit map properly removes
   964  // circuits from disk and the in-memory state when TrimOpenCircuits is used.
   965  // This test checks that a successful trim survives a restart, and that circuits
   966  // added before the restart can also be trimmed.
   967  func TestCircuitMapTrimOpenCircuits(t *testing.T) {
   968  	t.Parallel()
   969  
   970  	var (
   971  		chan1      = lnwire.NewShortChanIDFromInt(1)
   972  		chan2      = lnwire.NewShortChanIDFromInt(2)
   973  		circuitMap htlcswitch.CircuitMap
   974  		err        error
   975  	)
   976  
   977  	cfg, circuitMap := newCircuitMap(t)
   978  
   979  	const nCircuits = 10
   980  	const firstTrimIndex = 7
   981  	const secondTrimIndex = 3
   982  
   983  	// Create a list of all circuits that will be committed in the circuit
   984  	// map. The incoming HtlcIDs are chosen so that there is overlap with
   985  	// the outgoing HtlcIDs, but ensures that the test is not dependent on
   986  	// them being equal.
   987  	circuits := make([]*htlcswitch.PaymentCircuit, nCircuits)
   988  	for i := range circuits {
   989  		circuits[i] = &htlcswitch.PaymentCircuit{
   990  			Incoming: htlcswitch.CircuitKey{
   991  				ChanID: chan1,
   992  				HtlcID: uint64(i + 3),
   993  			},
   994  			ErrorEncrypter: htlcswitch.NewMockObfuscator(),
   995  		}
   996  	}
   997  
   998  	// First we will try to add an new circuit to the circuit map, this
   999  	// should succeed.
  1000  	_, err = circuitMap.CommitCircuits(circuits...)
  1001  	if err != nil {
  1002  		t.Fatalf("failed to commit circuits: %v", err)
  1003  	}
  1004  
  1005  	// Now create a list of the keystones that we will use to preemptively
  1006  	// open the circuits. We set the index as the outgoing HtlcID to i
  1007  	// simplify the indexing logic of the test.
  1008  	keystones := make([]htlcswitch.Keystone, nCircuits)
  1009  	for i := range keystones {
  1010  		keystones[i] = htlcswitch.Keystone{
  1011  			InKey: circuits[i].Incoming,
  1012  			OutKey: htlcswitch.CircuitKey{
  1013  				ChanID: chan2,
  1014  				HtlcID: uint64(i),
  1015  			},
  1016  		}
  1017  	}
  1018  
  1019  	// Open the circuits for the first time.
  1020  	err = circuitMap.OpenCircuits(keystones...)
  1021  	if err != nil {
  1022  		t.Fatalf("failed to open circuits: %v", err)
  1023  	}
  1024  
  1025  	// Check that all circuits are marked open.
  1026  	assertCircuitsOpenedPreRestart(t, circuitMap, circuits, keystones)
  1027  
  1028  	// Now trim up above outgoing htlcid `firstTrimIndex` (7). This should
  1029  	// leave the first 7 circuits open, and the rest should be reverted to
  1030  	// an unopened state.
  1031  	err = circuitMap.TrimOpenCircuits(chan2, firstTrimIndex)
  1032  	if err != nil {
  1033  		t.Fatalf("unable to trim circuits")
  1034  	}
  1035  
  1036  	assertCircuitsOpenedPreRestart(t,
  1037  		circuitMap,
  1038  		circuits[:firstTrimIndex],
  1039  		keystones[:firstTrimIndex],
  1040  	)
  1041  
  1042  	assertCircuitsNotOpenedPreRestart(
  1043  		t,
  1044  		circuitMap,
  1045  		circuits[firstTrimIndex:],
  1046  		keystones[firstTrimIndex:],
  1047  		firstTrimIndex,
  1048  	)
  1049  
  1050  	// Restart the circuit map, verify that the trim is reflected on
  1051  	// startup.
  1052  	cfg, circuitMap = restartCircuitMap(t, cfg)
  1053  
  1054  	assertCircuitsOpenedPostRestart(
  1055  		t,
  1056  		circuitMap,
  1057  		circuits[:firstTrimIndex],
  1058  		keystones[:firstTrimIndex],
  1059  	)
  1060  
  1061  	assertCircuitsNotOpenedPreRestart(
  1062  		t,
  1063  		circuitMap,
  1064  		circuits[firstTrimIndex:],
  1065  		keystones[firstTrimIndex:],
  1066  		firstTrimIndex,
  1067  	)
  1068  
  1069  	// Now, trim above outgoing htlcid `secondTrimIndex` (3). Only the first
  1070  	// three circuits should be open, with any others being reverted back to
  1071  	// unopened.
  1072  	err = circuitMap.TrimOpenCircuits(chan2, secondTrimIndex)
  1073  	if err != nil {
  1074  		t.Fatalf("unable to trim circuits")
  1075  	}
  1076  
  1077  	assertCircuitsOpenedPostRestart(
  1078  		t,
  1079  		circuitMap,
  1080  		circuits[:secondTrimIndex],
  1081  		keystones[:secondTrimIndex],
  1082  	)
  1083  
  1084  	assertCircuitsNotOpenedPreRestart(
  1085  		t,
  1086  		circuitMap,
  1087  		circuits[secondTrimIndex:],
  1088  		keystones[secondTrimIndex:],
  1089  		secondTrimIndex,
  1090  	)
  1091  
  1092  	// Restart the circuit map one last time to make sure the changes are
  1093  	// persisted.
  1094  	_, circuitMap = restartCircuitMap(t, cfg)
  1095  
  1096  	assertCircuitsOpenedPostRestart(
  1097  		t,
  1098  		circuitMap,
  1099  		circuits[:secondTrimIndex],
  1100  		keystones[:secondTrimIndex],
  1101  	)
  1102  
  1103  	assertCircuitsNotOpenedPreRestart(
  1104  		t,
  1105  		circuitMap,
  1106  		circuits[secondTrimIndex:],
  1107  		keystones[secondTrimIndex:],
  1108  		secondTrimIndex,
  1109  	)
  1110  }
  1111  
  1112  // TestCircuitMapCloseOpenCircuits asserts that the circuit map can properly
  1113  // close open circuits, and that it allows at most one response to do so
  1114  // successfully. It also checks that a circuit is reopened if the close was not
  1115  // persisted via DeleteCircuits, and can again be closed.
  1116  func TestCircuitMapCloseOpenCircuits(t *testing.T) {
  1117  	t.Parallel()
  1118  
  1119  	var (
  1120  		chan1      = lnwire.NewShortChanIDFromInt(1)
  1121  		chan2      = lnwire.NewShortChanIDFromInt(2)
  1122  		circuitMap htlcswitch.CircuitMap
  1123  		err        error
  1124  	)
  1125  
  1126  	cfg, circuitMap := newCircuitMap(t)
  1127  
  1128  	circuit := &htlcswitch.PaymentCircuit{
  1129  		Incoming: htlcswitch.CircuitKey{
  1130  			ChanID: chan1,
  1131  			HtlcID: 3,
  1132  		},
  1133  		ErrorEncrypter: &hop.SphinxErrorEncrypter{
  1134  			EphemeralKey: testEphemeralKey,
  1135  		},
  1136  	}
  1137  
  1138  	// First we will try to add an new circuit to the circuit map, this
  1139  	// should succeed.
  1140  	_, err = circuitMap.CommitCircuits(circuit)
  1141  	if err != nil {
  1142  		t.Fatalf("failed to commit circuits: %v", err)
  1143  	}
  1144  
  1145  	keystone := htlcswitch.Keystone{
  1146  		InKey: circuit.Incoming,
  1147  		OutKey: htlcswitch.CircuitKey{
  1148  			ChanID: chan2,
  1149  			HtlcID: 2,
  1150  		},
  1151  	}
  1152  
  1153  	// Open the circuit for the first time.
  1154  	err = circuitMap.OpenCircuits(keystone)
  1155  	if err != nil {
  1156  		t.Fatalf("failed to open circuits: %v", err)
  1157  	}
  1158  
  1159  	// Check that we can retrieve the open circuit if the circuit map before
  1160  	// the circuit map is restarted.
  1161  	circuit2 := circuitMap.LookupOpenCircuit(keystone.OutKey)
  1162  	if !reflect.DeepEqual(circuit, circuit2) {
  1163  		t.Fatalf("unexpected open circuit: got %v, want %v",
  1164  			circuit2, circuit)
  1165  	}
  1166  
  1167  	// Open the circuit for a second time, which should fail due to a
  1168  	// duplicate keystone
  1169  	err = circuitMap.OpenCircuits(keystone)
  1170  	if err != htlcswitch.ErrDuplicateKeystone {
  1171  		t.Fatalf("failed to open circuits: %v", err)
  1172  	}
  1173  
  1174  	// Close the open circuit for the first time, which should succeed.
  1175  	_, err = circuitMap.FailCircuit(circuit.Incoming)
  1176  	if err != nil {
  1177  		t.Fatalf("unable to close unopened circuit")
  1178  	}
  1179  
  1180  	// Closing the circuit a second time should result in a failure.
  1181  	_, err = circuitMap.FailCircuit(circuit.Incoming)
  1182  	if err != htlcswitch.ErrCircuitClosing {
  1183  		t.Fatalf("unable to close unopened circuit")
  1184  	}
  1185  
  1186  	// Now, restart the circuit map, which will cause the opened circuit to
  1187  	// be loaded from disk. Since we set the keystone on this circuit, it
  1188  	// should be restored as such in memory.
  1189  	//
  1190  	// NOTE: The channel db doesn't have any channel data, so no keystones
  1191  	// will be trimmed.
  1192  	_, circuitMap = restartCircuitMap(t, cfg)
  1193  
  1194  	// Close the open circuit for the first time, which should succeed.
  1195  	_, err = circuitMap.FailCircuit(circuit.Incoming)
  1196  	if err != nil {
  1197  		t.Fatalf("unable to close unopened circuit")
  1198  	}
  1199  
  1200  	// Closing the circuit a second time should result in a failure.
  1201  	_, err = circuitMap.FailCircuit(circuit.Incoming)
  1202  	if err != htlcswitch.ErrCircuitClosing {
  1203  		t.Fatalf("unable to close unopened circuit")
  1204  	}
  1205  }
  1206  
  1207  // TestCircuitMapCloseUnopenedCircuit tests that closing an unopened circuit
  1208  // allows at most semantics, and that the close is not persisted across
  1209  // restarts.
  1210  func TestCircuitMapCloseUnopenedCircuit(t *testing.T) {
  1211  	t.Parallel()
  1212  
  1213  	var (
  1214  		chan1      = lnwire.NewShortChanIDFromInt(1)
  1215  		circuitMap htlcswitch.CircuitMap
  1216  		err        error
  1217  	)
  1218  
  1219  	cfg, circuitMap := newCircuitMap(t)
  1220  
  1221  	circuit := &htlcswitch.PaymentCircuit{
  1222  		Incoming: htlcswitch.CircuitKey{
  1223  			ChanID: chan1,
  1224  			HtlcID: 3,
  1225  		},
  1226  		ErrorEncrypter: testExtracter,
  1227  	}
  1228  
  1229  	// First we will try to add an new circuit to the circuit map, this
  1230  	// should succeed.
  1231  	_, err = circuitMap.CommitCircuits(circuit)
  1232  	if err != nil {
  1233  		t.Fatalf("failed to commit circuits: %v", err)
  1234  	}
  1235  
  1236  	// Close the open circuit for the first time, which should succeed.
  1237  	_, err = circuitMap.FailCircuit(circuit.Incoming)
  1238  	if err != nil {
  1239  		t.Fatalf("unable to close unopened circuit")
  1240  	}
  1241  
  1242  	// Closing the circuit a second time should result in a failure.
  1243  	_, err = circuitMap.FailCircuit(circuit.Incoming)
  1244  	if err != htlcswitch.ErrCircuitClosing {
  1245  		t.Fatalf("unable to close unopened circuit")
  1246  	}
  1247  
  1248  	// Now, restart the circuit map, which will result in the circuit being
  1249  	// reopened, since no attempt to delete the circuit was made.
  1250  	_, circuitMap = restartCircuitMap(t, cfg)
  1251  
  1252  	// Close the open circuit for the first time, which should succeed.
  1253  	_, err = circuitMap.FailCircuit(circuit.Incoming)
  1254  	if err != nil {
  1255  		t.Fatalf("unable to close unopened circuit")
  1256  	}
  1257  
  1258  	// Closing the circuit a second time should result in a failure.
  1259  	_, err = circuitMap.FailCircuit(circuit.Incoming)
  1260  	if err != htlcswitch.ErrCircuitClosing {
  1261  		t.Fatalf("unable to close unopened circuit")
  1262  	}
  1263  }
  1264  
  1265  // TestCircuitMapDeleteUnopenedCircuit checks that an unopened circuit can be
  1266  // removed persistently from the circuit map.
  1267  func TestCircuitMapDeleteUnopenedCircuit(t *testing.T) {
  1268  	t.Parallel()
  1269  
  1270  	var (
  1271  		chan1      = lnwire.NewShortChanIDFromInt(1)
  1272  		circuitMap htlcswitch.CircuitMap
  1273  		err        error
  1274  	)
  1275  
  1276  	cfg, circuitMap := newCircuitMap(t)
  1277  
  1278  	circuit := &htlcswitch.PaymentCircuit{
  1279  		Incoming: htlcswitch.CircuitKey{
  1280  			ChanID: chan1,
  1281  			HtlcID: 3,
  1282  		},
  1283  		ErrorEncrypter: testExtracter,
  1284  	}
  1285  
  1286  	// First we will try to add an new circuit to the circuit map, this
  1287  	// should succeed.
  1288  	_, err = circuitMap.CommitCircuits(circuit)
  1289  	if err != nil {
  1290  		t.Fatalf("failed to commit circuits: %v", err)
  1291  	}
  1292  
  1293  	// Close the open circuit for the first time, which should succeed.
  1294  	_, err = circuitMap.FailCircuit(circuit.Incoming)
  1295  	if err != nil {
  1296  		t.Fatalf("unable to close unopened circuit")
  1297  	}
  1298  
  1299  	err = circuitMap.DeleteCircuits(circuit.Incoming)
  1300  	if err != nil {
  1301  		t.Fatalf("unable to close unopened circuit")
  1302  	}
  1303  
  1304  	// Check that we can retrieve the open circuit if the circuit map before
  1305  	// the circuit map is restarted.
  1306  	circuit2 := circuitMap.LookupCircuit(circuit.Incoming)
  1307  	if circuit2 != nil {
  1308  		t.Fatalf("unexpected open circuit: got %v, want %v",
  1309  			circuit2, nil)
  1310  	}
  1311  
  1312  	// Now, restart the circuit map, and check that the deletion survived
  1313  	// the restart.
  1314  	_, circuitMap = restartCircuitMap(t, cfg)
  1315  
  1316  	circuit2 = circuitMap.LookupCircuit(circuit.Incoming)
  1317  	if circuit2 != nil {
  1318  		t.Fatalf("unexpected open circuit: got %v, want %v",
  1319  			circuit2, nil)
  1320  	}
  1321  }
  1322  
  1323  // TestCircuitMapDeleteOpenCircuit checks that an open circuit can be removed
  1324  // persistently from the circuit map.
  1325  func TestCircuitMapDeleteOpenCircuit(t *testing.T) {
  1326  	t.Parallel()
  1327  
  1328  	var (
  1329  		chan1      = lnwire.NewShortChanIDFromInt(1)
  1330  		chan2      = lnwire.NewShortChanIDFromInt(2)
  1331  		circuitMap htlcswitch.CircuitMap
  1332  		err        error
  1333  	)
  1334  
  1335  	cfg, circuitMap := newCircuitMap(t)
  1336  
  1337  	circuit := &htlcswitch.PaymentCircuit{
  1338  		Incoming: htlcswitch.CircuitKey{
  1339  			ChanID: chan1,
  1340  			HtlcID: 3,
  1341  		},
  1342  		ErrorEncrypter: testExtracter,
  1343  	}
  1344  
  1345  	// First we will try to add an new circuit to the circuit map, this
  1346  	// should succeed.
  1347  	_, err = circuitMap.CommitCircuits(circuit)
  1348  	if err != nil {
  1349  		t.Fatalf("failed to commit circuits: %v", err)
  1350  	}
  1351  
  1352  	keystone := htlcswitch.Keystone{
  1353  		InKey: circuit.Incoming,
  1354  		OutKey: htlcswitch.CircuitKey{
  1355  			ChanID: chan2,
  1356  			HtlcID: 2,
  1357  		},
  1358  	}
  1359  
  1360  	// Open the circuit for the first time.
  1361  	err = circuitMap.OpenCircuits(keystone)
  1362  	if err != nil {
  1363  		t.Fatalf("failed to open circuits: %v", err)
  1364  	}
  1365  
  1366  	// Close the open circuit for the first time, which should succeed.
  1367  	_, err = circuitMap.FailCircuit(circuit.Incoming)
  1368  	if err != nil {
  1369  		t.Fatalf("unable to close unopened circuit")
  1370  	}
  1371  
  1372  	// Persistently remove the circuit identified by incoming chan id.
  1373  	err = circuitMap.DeleteCircuits(circuit.Incoming)
  1374  	if err != nil {
  1375  		t.Fatalf("unable to close unopened circuit")
  1376  	}
  1377  
  1378  	// Check that we can no longer retrieve the open circuit.
  1379  	circuit2 := circuitMap.LookupOpenCircuit(keystone.OutKey)
  1380  	if circuit2 != nil {
  1381  		t.Fatalf("unexpected open circuit: got %v, want %v",
  1382  			circuit2, nil)
  1383  	}
  1384  
  1385  	// Now, restart the circuit map, and check that the deletion survived
  1386  	// the restart.
  1387  	_, circuitMap = restartCircuitMap(t, cfg)
  1388  
  1389  	circuit2 = circuitMap.LookupOpenCircuit(keystone.OutKey)
  1390  	if circuit2 != nil {
  1391  		t.Fatalf("unexpected open circuit: got %v, want %v",
  1392  			circuit2, nil)
  1393  	}
  1394  }