package htlcswitch import ( "path/filepath" "testing" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lnwire" "github.com/stretchr/testify/require" ) // TestInsertAndDelete tests that an inserted resolution message can be // deleted. func TestInsertAndDelete(t *testing.T) { t.Parallel() scid := lnwire.NewShortChanIDFromInt(1) failResMsg := &contractcourt.ResolutionMsg{ SourceChan: scid, HtlcIndex: 2, Failure: &lnwire.FailTemporaryChannelFailure{}, } settleBytes := [32]byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, } settleResMsg := &contractcourt.ResolutionMsg{ SourceChan: scid, HtlcIndex: 3, PreImage: &settleBytes, } // Create the backend database and use it to create the resolution // store. dbPath := filepath.Join(t.TempDir(), "testdb") db, err := kvdb.Create( kvdb.BoltBackendName, dbPath, true, kvdb.DefaultDBTimeout, ) require.NoError(t, err) t.Cleanup(func() { db.Close() }) resStore := newResolutionStore(db) // We'll add the failure resolution message first, then check that it // exists in the store. err = resStore.addResolutionMsg(failResMsg) require.NoError(t, err) // Assert that checkResolutionMsg returns nil, signalling that the // resolution message was properly stored. outKey := &CircuitKey{ ChanID: failResMsg.SourceChan, HtlcID: failResMsg.HtlcIndex, } err = resStore.checkResolutionMsg(outKey) require.NoError(t, err) resMsgs, err := resStore.fetchAllResolutionMsg() require.NoError(t, err) require.Equal(t, 1, len(resMsgs)) // It should match failResMsg above. require.Equal(t, failResMsg.SourceChan, resMsgs[0].SourceChan) require.Equal(t, failResMsg.HtlcIndex, resMsgs[0].HtlcIndex) require.NotNil(t, resMsgs[0].Failure) require.Nil(t, resMsgs[0].PreImage) // We'll add the settleResMsg now. err = resStore.addResolutionMsg(settleResMsg) require.NoError(t, err) // Check that checkResolutionMsg returns nil for the settle CircuitKey. outKey.ChanID = settleResMsg.SourceChan outKey.HtlcID = settleResMsg.HtlcIndex err = resStore.checkResolutionMsg(outKey) require.NoError(t, err) // We should have two resolution messages in the store, one failure and // one success. resMsgs, err = resStore.fetchAllResolutionMsg() require.NoError(t, err) require.Equal(t, 2, len(resMsgs)) // The first resolution message should be the failure. require.Equal(t, failResMsg.SourceChan, resMsgs[0].SourceChan) require.Equal(t, failResMsg.HtlcIndex, resMsgs[0].HtlcIndex) require.NotNil(t, resMsgs[0].Failure) require.Nil(t, resMsgs[0].PreImage) // The second resolution message should be the success. require.Equal(t, settleResMsg.SourceChan, resMsgs[1].SourceChan) require.Equal(t, settleResMsg.HtlcIndex, resMsgs[1].HtlcIndex) require.Nil(t, resMsgs[1].Failure) require.Equal(t, settleBytes, *resMsgs[1].PreImage) // We'll now delete the failure resolution message and assert that only // the success is left. failKey := &CircuitKey{ ChanID: scid, HtlcID: failResMsg.HtlcIndex, } err = resStore.deleteResolutionMsg(failKey) require.NoError(t, err) // Assert that checkResolutionMsg returns errResMsgNotFound. err = resStore.checkResolutionMsg(failKey) require.ErrorIs(t, err, errResMsgNotFound) resMsgs, err = resStore.fetchAllResolutionMsg() require.NoError(t, err) require.Equal(t, 1, len(resMsgs)) // Assert that the success is left. require.Equal(t, settleResMsg.SourceChan, resMsgs[0].SourceChan) require.Equal(t, settleResMsg.HtlcIndex, resMsgs[0].HtlcIndex) require.Nil(t, resMsgs[0].Failure) require.Equal(t, settleBytes, *resMsgs[0].PreImage) // Now we'll delete the settle resolution message and assert that the // store is empty. settleKey := &CircuitKey{ ChanID: scid, HtlcID: settleResMsg.HtlcIndex, } err = resStore.deleteResolutionMsg(settleKey) require.NoError(t, err) // Assert that checkResolutionMsg returns errResMsgNotFound for the // settle key. err = resStore.checkResolutionMsg(settleKey) require.ErrorIs(t, err, errResMsgNotFound) resMsgs, err = resStore.fetchAllResolutionMsg() require.NoError(t, err) require.Equal(t, 0, len(resMsgs)) }