github.com/decred/dcrlnd@v0.7.6/channeldb/forwarding_package_test.go (about)

     1  package channeldb_test
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"path/filepath"
     7  	"runtime"
     8  	"testing"
     9  
    10  	"github.com/decred/dcrd/wire"
    11  	"github.com/decred/dcrlnd/channeldb"
    12  	"github.com/decred/dcrlnd/kvdb"
    13  	"github.com/decred/dcrlnd/lnwire"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  // TestPkgFilterBruteForce tests the behavior of a pkg filter up to size 1000,
    18  // which is greater than the number of HTLCs we permit on a commitment txn.
    19  // This should encapsulate every potential filter used in practice.
    20  func TestPkgFilterBruteForce(t *testing.T) {
    21  	t.Parallel()
    22  
    23  	checkPkgFilterRange(t, 1000)
    24  }
    25  
    26  // checkPkgFilterRange verifies the behavior of a pkg filter when doing a linear
    27  // insertion of `high` elements. This is primarily to test that IsFull functions
    28  // properly for all relevant sizes of `high`.
    29  func checkPkgFilterRange(t *testing.T, high int) {
    30  	for i := uint16(0); i < uint16(high); i++ {
    31  		f := channeldb.NewPkgFilter(i)
    32  
    33  		if f.Count() != i {
    34  			t.Fatalf("pkg filter count=%d is actually %d",
    35  				i, f.Count())
    36  		}
    37  		checkPkgFilterEncodeDecode(t, i, f)
    38  
    39  		for j := uint16(0); j < i; j++ {
    40  			if f.Contains(j) {
    41  				t.Fatalf("pkg filter count=%d contains %d "+
    42  					"before being added", i, j)
    43  			}
    44  
    45  			f.Set(j)
    46  			checkPkgFilterEncodeDecode(t, i, f)
    47  
    48  			if !f.Contains(j) {
    49  				t.Fatalf("pkg filter count=%d missing %d "+
    50  					"after being added", i, j)
    51  			}
    52  
    53  			if j < i-1 && f.IsFull() {
    54  				t.Fatalf("pkg filter count=%d already full", i)
    55  			}
    56  		}
    57  
    58  		if !f.IsFull() {
    59  			t.Fatalf("pkg filter count=%d not full", i)
    60  		}
    61  		checkPkgFilterEncodeDecode(t, i, f)
    62  	}
    63  }
    64  
    65  // TestPkgFilterRand uses a random permutation to verify the proper behavior of
    66  // the pkg filter if the entries are not inserted in-order.
    67  func TestPkgFilterRand(t *testing.T) {
    68  	t.Parallel()
    69  
    70  	checkPkgFilterRand(t, 3, 17)
    71  }
    72  
    73  // checkPkgFilterRand checks the behavior of a pkg filter by randomly inserting
    74  // indices and asserting the invariants. The order in which indices are inserted
    75  // is parameterized by a base `b` coprime to `p`, and using modular
    76  // exponentiation to generate all elements in [1,p).
    77  func checkPkgFilterRand(t *testing.T, b, p uint16) {
    78  	f := channeldb.NewPkgFilter(p)
    79  	var j = b
    80  	for i := uint16(1); i < p; i++ {
    81  		if f.Contains(j) {
    82  			t.Fatalf("pkg filter contains %d-%d "+
    83  				"before being added", i, j)
    84  		}
    85  
    86  		f.Set(j)
    87  		checkPkgFilterEncodeDecode(t, i, f)
    88  
    89  		if !f.Contains(j) {
    90  			t.Fatalf("pkg filter missing %d-%d "+
    91  				"after being added", i, j)
    92  		}
    93  
    94  		if i < p-1 && f.IsFull() {
    95  			t.Fatalf("pkg filter %d already full", i)
    96  		}
    97  		checkPkgFilterEncodeDecode(t, i, f)
    98  
    99  		j = (b * j) % p
   100  	}
   101  
   102  	// Set 0 independently, since it will never be emitted by the generator.
   103  	f.Set(0)
   104  	checkPkgFilterEncodeDecode(t, p, f)
   105  
   106  	if !f.IsFull() {
   107  		t.Fatalf("pkg filter count=%d not full", p)
   108  	}
   109  	checkPkgFilterEncodeDecode(t, p, f)
   110  }
   111  
   112  // checkPkgFilterEncodeDecode tests the serialization of a pkg filter by:
   113  //  1. writing it to a buffer
   114  //  2. verifying the number of bytes written matches the filter's Size()
   115  //  3. reconstructing the filter decoding the bytes
   116  //  4. checking that the two filters are the same according to Equal
   117  func checkPkgFilterEncodeDecode(t *testing.T, i uint16, f *channeldb.PkgFilter) {
   118  	var b bytes.Buffer
   119  	if err := f.Encode(&b); err != nil {
   120  		t.Fatalf("unable to serialize pkg filter: %v", err)
   121  	}
   122  
   123  	// +2 for uint16 length
   124  	size := uint16(len(b.Bytes()))
   125  	if size != f.Size() {
   126  		t.Fatalf("pkg filter count=%d serialized size differs, "+
   127  			"Size(): %d, len(bytes): %v", i, f.Size(), size)
   128  	}
   129  
   130  	reader := bytes.NewReader(b.Bytes())
   131  
   132  	f2 := &channeldb.PkgFilter{}
   133  	if err := f2.Decode(reader); err != nil {
   134  		t.Fatalf("unable to deserialize pkg filter: %v", err)
   135  	}
   136  
   137  	if !f.Equal(f2) {
   138  		t.Fatalf("pkg filter count=%v does is not equal "+
   139  			"after deserialization, want: %v, got %v",
   140  			i, f, f2)
   141  	}
   142  }
   143  
   144  var (
   145  	chanID = lnwire.NewChanIDFromOutPoint(&wire.OutPoint{})
   146  
   147  	adds = []channeldb.LogUpdate{
   148  		{
   149  			LogIndex: 0,
   150  			UpdateMsg: &lnwire.UpdateAddHTLC{
   151  				ChanID:      chanID,
   152  				ID:          1,
   153  				Amount:      100,
   154  				Expiry:      1000,
   155  				PaymentHash: [32]byte{0},
   156  			},
   157  		},
   158  		{
   159  			LogIndex: 1,
   160  			UpdateMsg: &lnwire.UpdateAddHTLC{
   161  				ChanID:      chanID,
   162  				ID:          1,
   163  				Amount:      101,
   164  				Expiry:      1001,
   165  				PaymentHash: [32]byte{1},
   166  			},
   167  		},
   168  	}
   169  
   170  	settleFails = []channeldb.LogUpdate{
   171  		{
   172  			LogIndex: 2,
   173  			UpdateMsg: &lnwire.UpdateFulfillHTLC{
   174  				ChanID:          chanID,
   175  				ID:              0,
   176  				PaymentPreimage: [32]byte{0},
   177  			},
   178  		},
   179  		{
   180  			LogIndex: 3,
   181  			UpdateMsg: &lnwire.UpdateFailHTLC{
   182  				ChanID: chanID,
   183  				ID:     1,
   184  				Reason: []byte{},
   185  			},
   186  		},
   187  	}
   188  )
   189  
   190  // TestPackagerEmptyFwdPkg checks that the state transitions exhibited by a
   191  // forwarding package that contains no adds, fails or settles. We expect that
   192  // the fwdpkg reaches FwdStateCompleted immediately after writing the forwarding
   193  // decision via SetFwdFilter.
   194  func TestPackagerEmptyFwdPkg(t *testing.T) {
   195  	t.Parallel()
   196  
   197  	db := makeFwdPkgDB(t, "")
   198  
   199  	shortChanID := lnwire.NewShortChanIDFromInt(1)
   200  	packager := channeldb.NewChannelPackager(shortChanID)
   201  
   202  	// To begin, there should be no forwarding packages on disk.
   203  	fwdPkgs := loadFwdPkgs(t, db, packager)
   204  	if len(fwdPkgs) != 0 {
   205  		t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs))
   206  	}
   207  
   208  	// Next, create and write a new forwarding package with no htlcs.
   209  	fwdPkg := channeldb.NewFwdPkg(shortChanID, 0, nil, nil)
   210  
   211  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   212  		return packager.AddFwdPkg(tx, fwdPkg)
   213  	}, func() {}); err != nil {
   214  		t.Fatalf("unable to add fwd pkg: %v", err)
   215  	}
   216  
   217  	// There should now be one fwdpkg on disk. Since no forwarding decision
   218  	// has been written, we expect it to be FwdStateLockedIn. With no HTLCs,
   219  	// the ack filter will have no elements, and should always return true.
   220  	fwdPkgs = loadFwdPkgs(t, db, packager)
   221  	if len(fwdPkgs) != 1 {
   222  		t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   223  	}
   224  	assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateLockedIn)
   225  	assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], 0, 0)
   226  	assertAckFilterIsFull(t, fwdPkgs[0], true)
   227  
   228  	// Now, write the forwarding decision. In this case, its just an empty
   229  	// fwd filter.
   230  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   231  		return packager.SetFwdFilter(tx, fwdPkg.Height, fwdPkg.FwdFilter)
   232  	}, func() {}); err != nil {
   233  		t.Fatalf("unable to set fwdfiter: %v", err)
   234  	}
   235  
   236  	// We should still have one package on disk. Since the forwarding
   237  	// decision has been written, it will minimally be in FwdStateProcessed.
   238  	// However with no htlcs, it should leap frog to FwdStateCompleted.
   239  	fwdPkgs = loadFwdPkgs(t, db, packager)
   240  	if len(fwdPkgs) != 1 {
   241  		t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   242  	}
   243  	assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateCompleted)
   244  	assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], 0, 0)
   245  	assertAckFilterIsFull(t, fwdPkgs[0], true)
   246  
   247  	// Lastly, remove the completed forwarding package from disk.
   248  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   249  		return packager.RemovePkg(tx, fwdPkg.Height)
   250  	}, func() {}); err != nil {
   251  		t.Fatalf("unable to remove fwdpkg: %v", err)
   252  	}
   253  
   254  	// Check that the fwd package was actually removed.
   255  	fwdPkgs = loadFwdPkgs(t, db, packager)
   256  	if len(fwdPkgs) != 0 {
   257  		t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs))
   258  	}
   259  }
   260  
   261  // TestPackagerOnlyAdds checks that the fwdpkg does not reach FwdStateCompleted
   262  // as soon as all the adds in the package have been acked using AckAddHtlcs.
   263  func TestPackagerOnlyAdds(t *testing.T) {
   264  	t.Parallel()
   265  
   266  	db := makeFwdPkgDB(t, "")
   267  
   268  	shortChanID := lnwire.NewShortChanIDFromInt(1)
   269  	packager := channeldb.NewChannelPackager(shortChanID)
   270  
   271  	// To begin, there should be no forwarding packages on disk.
   272  	fwdPkgs := loadFwdPkgs(t, db, packager)
   273  	if len(fwdPkgs) != 0 {
   274  		t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs))
   275  	}
   276  
   277  	// Next, create and write a new forwarding package that only has add
   278  	// htlcs.
   279  	fwdPkg := channeldb.NewFwdPkg(shortChanID, 0, adds, nil)
   280  
   281  	nAdds := len(adds)
   282  
   283  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   284  		return packager.AddFwdPkg(tx, fwdPkg)
   285  	}, func() {}); err != nil {
   286  		t.Fatalf("unable to add fwd pkg: %v", err)
   287  	}
   288  
   289  	// There should now be one fwdpkg on disk. Since no forwarding decision
   290  	// has been written, we expect it to be FwdStateLockedIn. The package
   291  	// has unacked add HTLCs, so the ack filter should not be full.
   292  	fwdPkgs = loadFwdPkgs(t, db, packager)
   293  	if len(fwdPkgs) != 1 {
   294  		t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   295  	}
   296  	assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateLockedIn)
   297  	assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], nAdds, 0)
   298  	assertAckFilterIsFull(t, fwdPkgs[0], false)
   299  
   300  	// Now, write the forwarding decision. Since we have not explicitly
   301  	// added any adds to the fwdfilter, this would indicate that all of the
   302  	// adds were 1) settled locally by this link (exit hop), or 2) the htlc
   303  	// was failed locally.
   304  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   305  		return packager.SetFwdFilter(tx, fwdPkg.Height, fwdPkg.FwdFilter)
   306  	}, func() {}); err != nil {
   307  		t.Fatalf("unable to set fwdfiter: %v", err)
   308  	}
   309  
   310  	for i := range adds {
   311  		// We should still have one package on disk. Since the forwarding
   312  		// decision has been written, it will minimally be in FwdStateProcessed.
   313  		// However not allf of the HTLCs have been acked, so should not
   314  		// have advanced further.
   315  		fwdPkgs = loadFwdPkgs(t, db, packager)
   316  		if len(fwdPkgs) != 1 {
   317  			t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   318  		}
   319  		assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateProcessed)
   320  		assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], nAdds, 0)
   321  		assertAckFilterIsFull(t, fwdPkgs[0], false)
   322  
   323  		addRef := channeldb.AddRef{
   324  			Height: fwdPkg.Height,
   325  			Index:  uint16(i),
   326  		}
   327  
   328  		if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   329  			return packager.AckAddHtlcs(tx, addRef)
   330  		}, func() {}); err != nil {
   331  			t.Fatalf("unable to ack add htlc: %v", err)
   332  		}
   333  	}
   334  
   335  	// We should still have one package on disk. Now that all adds have been
   336  	// acked, the ack filter should return true and the package should be
   337  	// FwdStateCompleted since there are no other settle/fail packets.
   338  	fwdPkgs = loadFwdPkgs(t, db, packager)
   339  	if len(fwdPkgs) != 1 {
   340  		t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   341  	}
   342  	assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateCompleted)
   343  	assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], nAdds, 0)
   344  	assertAckFilterIsFull(t, fwdPkgs[0], true)
   345  
   346  	// Lastly, remove the completed forwarding package from disk.
   347  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   348  		return packager.RemovePkg(tx, fwdPkg.Height)
   349  	}, func() {}); err != nil {
   350  		t.Fatalf("unable to remove fwdpkg: %v", err)
   351  	}
   352  
   353  	// Check that the fwd package was actually removed.
   354  	fwdPkgs = loadFwdPkgs(t, db, packager)
   355  	if len(fwdPkgs) != 0 {
   356  		t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs))
   357  	}
   358  }
   359  
   360  // TestPackagerOnlySettleFails asserts that the fwdpkg remains in
   361  // FwdStateProcessed after writing the forwarding decision when there are no
   362  // adds in the fwdpkg. We expect this because an empty FwdFilter will always
   363  // return true, but we are still waiting for the remaining fails and settles to
   364  // be deleted.
   365  func TestPackagerOnlySettleFails(t *testing.T) {
   366  	t.Parallel()
   367  
   368  	db := makeFwdPkgDB(t, "")
   369  
   370  	shortChanID := lnwire.NewShortChanIDFromInt(1)
   371  	packager := channeldb.NewChannelPackager(shortChanID)
   372  
   373  	// To begin, there should be no forwarding packages on disk.
   374  	fwdPkgs := loadFwdPkgs(t, db, packager)
   375  	if len(fwdPkgs) != 0 {
   376  		t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs))
   377  	}
   378  
   379  	// Next, create and write a new forwarding package that only has add
   380  	// htlcs.
   381  	fwdPkg := channeldb.NewFwdPkg(shortChanID, 0, nil, settleFails)
   382  
   383  	nSettleFails := len(settleFails)
   384  
   385  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   386  		return packager.AddFwdPkg(tx, fwdPkg)
   387  	}, func() {}); err != nil {
   388  		t.Fatalf("unable to add fwd pkg: %v", err)
   389  	}
   390  
   391  	// There should now be one fwdpkg on disk. Since no forwarding decision
   392  	// has been written, we expect it to be FwdStateLockedIn. The package
   393  	// has unacked add HTLCs, so the ack filter should not be full.
   394  	fwdPkgs = loadFwdPkgs(t, db, packager)
   395  	if len(fwdPkgs) != 1 {
   396  		t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   397  	}
   398  	assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateLockedIn)
   399  	assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], 0, nSettleFails)
   400  	assertAckFilterIsFull(t, fwdPkgs[0], true)
   401  
   402  	// Now, write the forwarding decision. Since we have not explicitly
   403  	// added any adds to the fwdfilter, this would indicate that all of the
   404  	// adds were 1) settled locally by this link (exit hop), or 2) the htlc
   405  	// was failed locally.
   406  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   407  		return packager.SetFwdFilter(tx, fwdPkg.Height, fwdPkg.FwdFilter)
   408  	}, func() {}); err != nil {
   409  		t.Fatalf("unable to set fwdfiter: %v", err)
   410  	}
   411  
   412  	for i := range settleFails {
   413  		// We should still have one package on disk. Since the
   414  		// forwarding decision has been written, it will minimally be in
   415  		// FwdStateProcessed. However, not all of the HTLCs have been
   416  		// acked, so should not have advanced further.
   417  		fwdPkgs = loadFwdPkgs(t, db, packager)
   418  		if len(fwdPkgs) != 1 {
   419  			t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   420  		}
   421  		assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateProcessed)
   422  		assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], 0, nSettleFails)
   423  		assertSettleFailFilterIsFull(t, fwdPkgs[0], false)
   424  		assertAckFilterIsFull(t, fwdPkgs[0], true)
   425  
   426  		failSettleRef := channeldb.SettleFailRef{
   427  			Source: shortChanID,
   428  			Height: fwdPkg.Height,
   429  			Index:  uint16(i),
   430  		}
   431  
   432  		if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   433  			return packager.AckSettleFails(tx, failSettleRef)
   434  		}, func() {}); err != nil {
   435  			t.Fatalf("unable to ack add htlc: %v", err)
   436  		}
   437  	}
   438  
   439  	// We should still have one package on disk. Now that all settles and
   440  	// fails have been removed, package should be FwdStateCompleted since
   441  	// there are no other add packets.
   442  	fwdPkgs = loadFwdPkgs(t, db, packager)
   443  	if len(fwdPkgs) != 1 {
   444  		t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   445  	}
   446  	assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateCompleted)
   447  	assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], 0, nSettleFails)
   448  	assertSettleFailFilterIsFull(t, fwdPkgs[0], true)
   449  	assertAckFilterIsFull(t, fwdPkgs[0], true)
   450  
   451  	// Lastly, remove the completed forwarding package from disk.
   452  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   453  		return packager.RemovePkg(tx, fwdPkg.Height)
   454  	}, func() {}); err != nil {
   455  		t.Fatalf("unable to remove fwdpkg: %v", err)
   456  	}
   457  
   458  	// Check that the fwd package was actually removed.
   459  	fwdPkgs = loadFwdPkgs(t, db, packager)
   460  	if len(fwdPkgs) != 0 {
   461  		t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs))
   462  	}
   463  }
   464  
   465  // TestPackagerAddsThenSettleFails writes a fwdpkg containing both adds and
   466  // settle/fails, then checks the behavior when the adds are acked before any of
   467  // the settle fails. Here we expect pkg to remain in FwdStateProcessed while the
   468  // remainder of the fail/settles are being deleted.
   469  func TestPackagerAddsThenSettleFails(t *testing.T) {
   470  	t.Parallel()
   471  
   472  	db := makeFwdPkgDB(t, "")
   473  
   474  	shortChanID := lnwire.NewShortChanIDFromInt(1)
   475  	packager := channeldb.NewChannelPackager(shortChanID)
   476  
   477  	// To begin, there should be no forwarding packages on disk.
   478  	fwdPkgs := loadFwdPkgs(t, db, packager)
   479  	if len(fwdPkgs) != 0 {
   480  		t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs))
   481  	}
   482  
   483  	// Next, create and write a new forwarding package that only has add
   484  	// htlcs.
   485  	fwdPkg := channeldb.NewFwdPkg(shortChanID, 0, adds, settleFails)
   486  
   487  	nAdds := len(adds)
   488  	nSettleFails := len(settleFails)
   489  
   490  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   491  		return packager.AddFwdPkg(tx, fwdPkg)
   492  	}, func() {}); err != nil {
   493  		t.Fatalf("unable to add fwd pkg: %v", err)
   494  	}
   495  
   496  	// There should now be one fwdpkg on disk. Since no forwarding decision
   497  	// has been written, we expect it to be FwdStateLockedIn. The package
   498  	// has unacked add HTLCs, so the ack filter should not be full.
   499  	fwdPkgs = loadFwdPkgs(t, db, packager)
   500  	if len(fwdPkgs) != 1 {
   501  		t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   502  	}
   503  	assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateLockedIn)
   504  	assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], nAdds, nSettleFails)
   505  	assertAckFilterIsFull(t, fwdPkgs[0], false)
   506  
   507  	// Now, write the forwarding decision. Since we have not explicitly
   508  	// added any adds to the fwdfilter, this would indicate that all of the
   509  	// adds were 1) settled locally by this link (exit hop), or 2) the htlc
   510  	// was failed locally.
   511  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   512  		return packager.SetFwdFilter(tx, fwdPkg.Height, fwdPkg.FwdFilter)
   513  	}, func() {}); err != nil {
   514  		t.Fatalf("unable to set fwdfiter: %v", err)
   515  	}
   516  
   517  	for i := range adds {
   518  		// We should still have one package on disk. Since the forwarding
   519  		// decision has been written, it will minimally be in FwdStateProcessed.
   520  		// However not allf of the HTLCs have been acked, so should not
   521  		// have advanced further.
   522  		fwdPkgs = loadFwdPkgs(t, db, packager)
   523  		if len(fwdPkgs) != 1 {
   524  			t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   525  		}
   526  		assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateProcessed)
   527  		assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], nAdds, nSettleFails)
   528  		assertSettleFailFilterIsFull(t, fwdPkgs[0], false)
   529  		assertAckFilterIsFull(t, fwdPkgs[0], false)
   530  
   531  		addRef := channeldb.AddRef{
   532  			Height: fwdPkg.Height,
   533  			Index:  uint16(i),
   534  		}
   535  
   536  		if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   537  			return packager.AckAddHtlcs(tx, addRef)
   538  		}, func() {}); err != nil {
   539  			t.Fatalf("unable to ack add htlc: %v", err)
   540  		}
   541  	}
   542  
   543  	for i := range settleFails {
   544  		// We should still have one package on disk. Since the
   545  		// forwarding decision has been written, it will minimally be in
   546  		// FwdStateProcessed.  However not allf of the HTLCs have been
   547  		// acked, so should not have advanced further.
   548  		fwdPkgs = loadFwdPkgs(t, db, packager)
   549  		if len(fwdPkgs) != 1 {
   550  			t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   551  		}
   552  		assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateProcessed)
   553  		assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], nAdds, nSettleFails)
   554  		assertSettleFailFilterIsFull(t, fwdPkgs[0], false)
   555  		assertAckFilterIsFull(t, fwdPkgs[0], true)
   556  
   557  		failSettleRef := channeldb.SettleFailRef{
   558  			Source: shortChanID,
   559  			Height: fwdPkg.Height,
   560  			Index:  uint16(i),
   561  		}
   562  
   563  		if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   564  			return packager.AckSettleFails(tx, failSettleRef)
   565  		}, func() {}); err != nil {
   566  			t.Fatalf("unable to remove settle/fail htlc: %v", err)
   567  		}
   568  	}
   569  
   570  	// We should still have one package on disk. Now that all settles and
   571  	// fails have been removed, package should be FwdStateCompleted since
   572  	// there are no other add packets.
   573  	fwdPkgs = loadFwdPkgs(t, db, packager)
   574  	if len(fwdPkgs) != 1 {
   575  		t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   576  	}
   577  	assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateCompleted)
   578  	assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], nAdds, nSettleFails)
   579  	assertSettleFailFilterIsFull(t, fwdPkgs[0], true)
   580  	assertAckFilterIsFull(t, fwdPkgs[0], true)
   581  
   582  	// Lastly, remove the completed forwarding package from disk.
   583  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   584  		return packager.RemovePkg(tx, fwdPkg.Height)
   585  	}, func() {}); err != nil {
   586  		t.Fatalf("unable to remove fwdpkg: %v", err)
   587  	}
   588  
   589  	// Check that the fwd package was actually removed.
   590  	fwdPkgs = loadFwdPkgs(t, db, packager)
   591  	if len(fwdPkgs) != 0 {
   592  		t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs))
   593  	}
   594  }
   595  
   596  // TestPackagerSettleFailsThenAdds writes a fwdpkg with both adds and
   597  // settle/fails, then checks the behavior when the settle/fails are removed
   598  // before any of the adds have been acked. This should cause the fwdpkg to
   599  // remain in FwdStateProcessed until the final ack is recorded, at which point
   600  // it should be promoted directly to FwdStateCompleted.since all adds have been
   601  // removed.
   602  func TestPackagerSettleFailsThenAdds(t *testing.T) {
   603  	t.Parallel()
   604  
   605  	db := makeFwdPkgDB(t, "")
   606  
   607  	shortChanID := lnwire.NewShortChanIDFromInt(1)
   608  	packager := channeldb.NewChannelPackager(shortChanID)
   609  
   610  	// To begin, there should be no forwarding packages on disk.
   611  	fwdPkgs := loadFwdPkgs(t, db, packager)
   612  	if len(fwdPkgs) != 0 {
   613  		t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs))
   614  	}
   615  
   616  	// Next, create and write a new forwarding package that has both add
   617  	// and settle/fail htlcs.
   618  	fwdPkg := channeldb.NewFwdPkg(shortChanID, 0, adds, settleFails)
   619  
   620  	nAdds := len(adds)
   621  	nSettleFails := len(settleFails)
   622  
   623  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   624  		return packager.AddFwdPkg(tx, fwdPkg)
   625  	}, func() {}); err != nil {
   626  		t.Fatalf("unable to add fwd pkg: %v", err)
   627  	}
   628  
   629  	// There should now be one fwdpkg on disk. Since no forwarding decision
   630  	// has been written, we expect it to be FwdStateLockedIn. The package
   631  	// has unacked add HTLCs, so the ack filter should not be full.
   632  	fwdPkgs = loadFwdPkgs(t, db, packager)
   633  	if len(fwdPkgs) != 1 {
   634  		t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   635  	}
   636  	assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateLockedIn)
   637  	assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], nAdds, nSettleFails)
   638  	assertAckFilterIsFull(t, fwdPkgs[0], false)
   639  
   640  	// Now, write the forwarding decision. Since we have not explicitly
   641  	// added any adds to the fwdfilter, this would indicate that all of the
   642  	// adds were 1) settled locally by this link (exit hop), or 2) the htlc
   643  	// was failed locally.
   644  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   645  		return packager.SetFwdFilter(tx, fwdPkg.Height, fwdPkg.FwdFilter)
   646  	}, func() {}); err != nil {
   647  		t.Fatalf("unable to set fwdfiter: %v", err)
   648  	}
   649  
   650  	// Simulate another channel deleting the settle/fails it received from
   651  	// the original fwd pkg.
   652  	// TODO(conner): use different packager/s?
   653  	for i := range settleFails {
   654  		// We should still have one package on disk. Since the
   655  		// forwarding decision has been written, it will minimally be in
   656  		// FwdStateProcessed.  However none all of the add HTLCs have
   657  		// been acked, so should not have advanced further.
   658  		fwdPkgs = loadFwdPkgs(t, db, packager)
   659  		if len(fwdPkgs) != 1 {
   660  			t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   661  		}
   662  		assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateProcessed)
   663  		assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], nAdds, nSettleFails)
   664  		assertSettleFailFilterIsFull(t, fwdPkgs[0], false)
   665  		assertAckFilterIsFull(t, fwdPkgs[0], false)
   666  
   667  		failSettleRef := channeldb.SettleFailRef{
   668  			Source: shortChanID,
   669  			Height: fwdPkg.Height,
   670  			Index:  uint16(i),
   671  		}
   672  
   673  		if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   674  			return packager.AckSettleFails(tx, failSettleRef)
   675  		}, func() {}); err != nil {
   676  			t.Fatalf("unable to remove settle/fail htlc: %v", err)
   677  		}
   678  	}
   679  
   680  	// Now simulate this channel receiving a fail/settle for the adds in the
   681  	// fwdpkg.
   682  	for i := range adds {
   683  		// Again, we should still have one package on disk and be in
   684  		// FwdStateProcessed. This should not change until all of the
   685  		// add htlcs have been acked.
   686  		fwdPkgs = loadFwdPkgs(t, db, packager)
   687  		if len(fwdPkgs) != 1 {
   688  			t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   689  		}
   690  		assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateProcessed)
   691  		assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], nAdds, nSettleFails)
   692  		assertSettleFailFilterIsFull(t, fwdPkgs[0], true)
   693  		assertAckFilterIsFull(t, fwdPkgs[0], false)
   694  
   695  		addRef := channeldb.AddRef{
   696  			Height: fwdPkg.Height,
   697  			Index:  uint16(i),
   698  		}
   699  
   700  		if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   701  			return packager.AckAddHtlcs(tx, addRef)
   702  		}, func() {}); err != nil {
   703  			t.Fatalf("unable to ack add htlc: %v", err)
   704  		}
   705  	}
   706  
   707  	// We should still have one package on disk. Now that all settles and
   708  	// fails have been removed, package should be FwdStateCompleted since
   709  	// there are no other add packets.
   710  	fwdPkgs = loadFwdPkgs(t, db, packager)
   711  	if len(fwdPkgs) != 1 {
   712  		t.Fatalf("expected 1 fwdpkg, instead found %d", len(fwdPkgs))
   713  	}
   714  	assertFwdPkgState(t, fwdPkgs[0], channeldb.FwdStateCompleted)
   715  	assertFwdPkgNumAddsSettleFails(t, fwdPkgs[0], nAdds, nSettleFails)
   716  	assertSettleFailFilterIsFull(t, fwdPkgs[0], true)
   717  	assertAckFilterIsFull(t, fwdPkgs[0], true)
   718  
   719  	// Lastly, remove the completed forwarding package from disk.
   720  	if err := kvdb.Update(db, func(tx kvdb.RwTx) error {
   721  		return packager.RemovePkg(tx, fwdPkg.Height)
   722  	}, func() {}); err != nil {
   723  		t.Fatalf("unable to remove fwdpkg: %v", err)
   724  	}
   725  
   726  	// Check that the fwd package was actually removed.
   727  	fwdPkgs = loadFwdPkgs(t, db, packager)
   728  	if len(fwdPkgs) != 0 {
   729  		t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs))
   730  	}
   731  }
   732  
   733  // TestPackagerWipeAll checks that when the method is called, all the related
   734  // forwarding packages will be removed.
   735  func TestPackagerWipeAll(t *testing.T) {
   736  	t.Parallel()
   737  
   738  	db := makeFwdPkgDB(t, "")
   739  
   740  	shortChanID := lnwire.NewShortChanIDFromInt(1)
   741  	packager := channeldb.NewChannelPackager(shortChanID)
   742  
   743  	// To begin, there should be no forwarding packages on disk.
   744  	fwdPkgs := loadFwdPkgs(t, db, packager)
   745  	require.Empty(t, fwdPkgs, "no forwarding packages should exist")
   746  
   747  	// Now, check we can wipe without error since it's a noop.
   748  	err := kvdb.Update(db, packager.Wipe, func() {})
   749  	require.NoError(t, err, "unable to wipe fwdpkg")
   750  
   751  	// Next, create and write two forwarding packages with no htlcs.
   752  	fwdPkg1 := channeldb.NewFwdPkg(shortChanID, 0, nil, nil)
   753  	fwdPkg2 := channeldb.NewFwdPkg(shortChanID, 1, nil, nil)
   754  
   755  	err = kvdb.Update(db, func(tx kvdb.RwTx) error {
   756  		if err := packager.AddFwdPkg(tx, fwdPkg2); err != nil {
   757  			return err
   758  		}
   759  		return packager.AddFwdPkg(tx, fwdPkg1)
   760  	}, func() {})
   761  	require.NoError(t, err, "unable to add fwd pkg")
   762  
   763  	// There should now be two fwdpkgs on disk.
   764  	fwdPkgs = loadFwdPkgs(t, db, packager)
   765  	require.Equal(t, 2, len(fwdPkgs), "expected 2 fwdpkg")
   766  
   767  	// Now, wipe all forwarding packages from disk.
   768  	err = kvdb.Update(db, packager.Wipe, func() {})
   769  	require.NoError(t, err, "unable to wipe fwdpkg")
   770  
   771  	// Check that the packages were actually removed.
   772  	fwdPkgs = loadFwdPkgs(t, db, packager)
   773  	require.Empty(t, fwdPkgs, "no forwarding packages should exist")
   774  }
   775  
   776  // assertFwdPkgState checks the current state of a fwdpkg meets our
   777  // expectations.
   778  func assertFwdPkgState(t *testing.T, fwdPkg *channeldb.FwdPkg,
   779  	state channeldb.FwdState) {
   780  	_, _, line, _ := runtime.Caller(1)
   781  	if fwdPkg.State != state {
   782  		t.Fatalf("line %d: expected fwdpkg in state %v, found %v",
   783  			line, state, fwdPkg.State)
   784  	}
   785  }
   786  
   787  // assertFwdPkgNumAddsSettleFails checks that the number of adds and
   788  // settle/fail log updates are correct.
   789  func assertFwdPkgNumAddsSettleFails(t *testing.T, fwdPkg *channeldb.FwdPkg,
   790  	expectedNumAdds, expectedNumSettleFails int) {
   791  	_, _, line, _ := runtime.Caller(1)
   792  	if len(fwdPkg.Adds) != expectedNumAdds {
   793  		t.Fatalf("line %d: expected fwdpkg to have %d adds, found %d",
   794  			line, expectedNumAdds, len(fwdPkg.Adds))
   795  	}
   796  
   797  	if len(fwdPkg.SettleFails) != expectedNumSettleFails {
   798  		t.Fatalf("line %d: expected fwdpkg to have %d settle/fails, found %d",
   799  			line, expectedNumSettleFails, len(fwdPkg.SettleFails))
   800  	}
   801  }
   802  
   803  // assertAckFilterIsFull checks whether or not a fwdpkg's ack filter matches our
   804  // expected full-ness.
   805  func assertAckFilterIsFull(t *testing.T, fwdPkg *channeldb.FwdPkg, expected bool) {
   806  	_, _, line, _ := runtime.Caller(1)
   807  	if fwdPkg.AckFilter.IsFull() != expected {
   808  		t.Fatalf("line %d: expected fwdpkg ack filter IsFull to be %v, "+
   809  			"found %v", line, expected, fwdPkg.AckFilter.IsFull())
   810  	}
   811  }
   812  
   813  // assertSettleFailFilterIsFull checks whether or not a fwdpkg's settle fail
   814  // filter matches our expected full-ness.
   815  func assertSettleFailFilterIsFull(t *testing.T, fwdPkg *channeldb.FwdPkg, expected bool) {
   816  	_, _, line, _ := runtime.Caller(1)
   817  	if fwdPkg.SettleFailFilter.IsFull() != expected {
   818  		t.Fatalf("line %d: expected fwdpkg settle/fail filter IsFull to be %v, "+
   819  			"found %v", line, expected, fwdPkg.SettleFailFilter.IsFull())
   820  	}
   821  }
   822  
   823  // loadFwdPkgs is a helper method that reads all forwarding packages for a
   824  // particular packager.
   825  func loadFwdPkgs(t *testing.T, db kvdb.Backend,
   826  	packager channeldb.FwdPackager) []*channeldb.FwdPkg {
   827  
   828  	var fwdPkgs []*channeldb.FwdPkg
   829  	if err := kvdb.View(db, func(tx kvdb.RTx) error {
   830  		var err error
   831  		fwdPkgs, err = packager.LoadFwdPkgs(tx)
   832  		return err
   833  	}, func() {
   834  		fwdPkgs = nil
   835  	}); err != nil {
   836  		t.Fatalf("unable to load fwd pkgs: %v", err)
   837  	}
   838  
   839  	return fwdPkgs
   840  }
   841  
   842  // makeFwdPkgDB initializes a test database for forwarding packages. If the
   843  // provided path is an empty, it will create a temp dir/file to use.
   844  func makeFwdPkgDB(t *testing.T, path string) kvdb.Backend {
   845  	if path == "" {
   846  		var err error
   847  		path, err = ioutil.TempDir("", "fwdpkgdb")
   848  		if err != nil {
   849  			t.Fatalf("unable to create temp path: %v", err)
   850  		}
   851  
   852  		path = filepath.Join(path, "fwdpkg.db")
   853  	}
   854  
   855  	bdb, err := kvdb.Create(
   856  		kvdb.BoltBackendName, path, true, kvdb.DefaultDBTimeout,
   857  	)
   858  	if err != nil {
   859  		t.Fatalf("unable to open bboltdb: %v", err)
   860  	}
   861  
   862  	return bdb
   863  }