lnwallet: make spendTx param in NewBreachRetribution optional

In this commit, the NewBreachRetribution function is adjusted so that a
caller can optionally set the spendTx parameter to nil. In this case,
the function will check the revocation log to see if the local and
remote amount fields are available there and use them if they are.
If the fields are not present, which they might not be given a previous
migration that removed the fields, then an error is returned.
This commit is contained in:
Elle Mouton committed 2023-02-16 20:47:35 +02:00
1 parent 2c786ec66f
commit 91a2cd45d8
2 files changed
+136 -28

No files matched your search

+67 -5
View File
@@ -9482,7 +9482,7 @@ func TestCreateHtlcRetribution(t *testing.T) {
}
// TestCreateBreachRetribution checks that `createBreachRetribution` behaves as
// epxected.
// expected.
func TestCreateBreachRetribution(t *testing.T) {
t.Parallel()
@@ -9524,11 +9524,15 @@ func TestCreateBreachRetribution(t *testing.T) {
}
// Create a dummy revocation log.
ourAmtMsat := lnwire.MilliSatoshi(ourAmt * 1000)
theirAmtMsat := lnwire.MilliSatoshi(theirAmt * 1000)
revokedLog := channeldb.RevocationLog{
CommitTxHash: commitHash,
OurOutputIndex: uint16(localIndex),
TheirOutputIndex: uint16(remoteIndex),
HTLCEntries: []*channeldb.HTLCEntry{htlc},
TheirBalance: &theirAmtMsat,
OurBalance: &ourAmtMsat,
}
// Create a log with an empty local output index.
@@ -9545,14 +9549,25 @@ func TestCreateBreachRetribution(t *testing.T) {
expectedErr error
expectedOurAmt int64
expectedTheirAmt int64
noSpendTx bool
}{
{
name: "create retribution successfully",
name: "create retribution successfully " +
"with spend tx",
revocationLog: &revokedLog,
expectedErr: nil,
expectedOurAmt: ourAmt,
expectedTheirAmt: theirAmt,
},
{
name: "create retribution successfully " +
"without spend tx",
revocationLog: &revokedLog,
expectedErr: nil,
expectedOurAmt: ourAmt,
expectedTheirAmt: theirAmt,
noSpendTx: true,
},
{
name: "fail due to our index too big",
revocationLog: &channeldb.RevocationLog{
@@ -9568,19 +9583,39 @@ func TestCreateBreachRetribution(t *testing.T) {
expectedErr: ErrOutputIndexOutOfRange,
},
{
name: "empty local output index",
name: "empty local output index with spend " +
"tx",
revocationLog: &revokedLogNoLocal,
expectedErr: nil,
expectedOurAmt: 0,
expectedTheirAmt: theirAmt,
},
{
name: "empty remote output index",
name: "empty local output index without spend " +
"tx",
revocationLog: &revokedLogNoLocal,
expectedErr: nil,
expectedOurAmt: 0,
expectedTheirAmt: theirAmt,
noSpendTx: true,
},
{
name: "empty remote output index with spend " +
"tx",
revocationLog: &revokedLogNoRemote,
expectedErr: nil,
expectedOurAmt: ourAmt,
expectedTheirAmt: 0,
},
{
name: "empty remote output index without spend " +
"tx",
revocationLog: &revokedLogNoRemote,
expectedErr: nil,
expectedOurAmt: ourAmt,
expectedTheirAmt: 0,
noSpendTx: true,
},
}
// assertRetribution is a helper closure that checks a given breach
@@ -9623,8 +9658,13 @@ func TestCreateBreachRetribution(t *testing.T) {
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
tx := spendTx
if tc.noSpendTx {
tx = nil
}
br, our, their, err := createBreachRetribution(
tc.revocationLog, spendTx,
tc.revocationLog, tx,
aliceChannel.channelState, keyRing,
dummyPrivate, leaseExpiry,
)
@@ -9748,6 +9788,13 @@ func testNewBreachRetribution(t *testing.T, chanType channeldb.ChannelType) {
)
require.ErrorIs(t, err, channeldb.ErrNoPastDeltas)
// We also check that the same error is returned if no breach tx is
// provided.
_, err = NewBreachRetribution(
aliceChannel.channelState, stateNum, breachHeight, nil,
)
require.ErrorIs(t, err, channeldb.ErrNoPastDeltas)
// We now force a state transition which will give us a revocation log
// at height 0.
txid := aliceChannel.channelState.RemoteCommitment.CommitTx.TxHash()
@@ -9797,10 +9844,25 @@ func testNewBreachRetribution(t *testing.T, chanType channeldb.ChannelType) {
t.Log(spew.Sdump(breachTx))
assertRetribution(br, 1, 0)
// Repeat the check but with the breach tx set to nil. This should work
// since the necessary info should now be found in the revocation log.
br, err = NewBreachRetribution(
aliceChannel.channelState, stateNum, breachHeight, nil,
)
require.NoError(t, err)
assertRetribution(br, 1, 0)
// Create the retribution using a stateNum+1 and we should expect an
// error.
_, err = NewBreachRetribution(
aliceChannel.channelState, stateNum+1, breachHeight, breachTx,
)
require.ErrorIs(t, err, channeldb.ErrLogEntryNotFound)
// Once again, repeat the check for the case when no breach tx is
// provided.
_, err = NewBreachRetribution(
aliceChannel.channelState, stateNum+1, breachHeight, nil,
)
require.ErrorIs(t, err, channeldb.ErrLogEntryNotFound)
}