invoices: move UpdateInvoice implementation to the invoices package

With the introducation of the `InvoiceUpdater` interface we are now
able to move the non-kv parts of `UpdateInvoice` completely under
the invoices package. This is a preprequisite for being able to use
the same code-base for the sql InvoiceDB implementation of
UpdateInvoice.
This commit is contained in:
Andras Banki-Horvath committed 2024-02-19 20:47:24 +01:00
1 parent ecbfc46312
commit 6b0931af82
4 files changed
+1512 -1491

No files matched your search

-676
View File
@@ -2333,682 +2333,6 @@ func testUpdateHTLCPreimages(t *testing.T, test updateHTLCPreimageTestCase) {
require.Equal(t, test.expError, err)
}
type updateHTLCTest struct {
name string
input invpkg.InvoiceHTLC
invState invpkg.ContractState
setID *[32]byte
output invpkg.InvoiceHTLC
expErr error
}
// TestUpdateHTLC asserts the behavior of the updateHTLC method in various
// scenarios for MPP and AMP.
func TestUpdateHTLC(t *testing.T) {
t.Parallel()
setID := [32]byte{0x01}
ampRecord := record.NewAMP([32]byte{0x02}, setID, 3)
preimage := lntypes.Preimage{0x04}
hash := preimage.Hash()
diffSetID := [32]byte{0x05}
fakePreimage := lntypes.Preimage{0x06}
testAlreadyNow := time.Now()
tests := []updateHTLCTest{
{
name: "MPP accept",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: nil,
},
invState: invpkg.ContractAccepted,
setID: nil,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: nil,
},
expErr: nil,
},
{
name: "MPP settle",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: nil,
},
invState: invpkg.ContractSettled,
setID: nil,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testNow,
Expiry: 40,
State: invpkg.HtlcStateSettled,
CustomRecords: make(record.CustomSet),
AMP: nil,
},
expErr: nil,
},
{
name: "MPP cancel",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: nil,
},
invState: invpkg.ContractCanceled,
setID: nil,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testNow,
Expiry: 40,
State: invpkg.HtlcStateCanceled,
CustomRecords: make(record.CustomSet),
AMP: nil,
},
expErr: nil,
},
{
name: "AMP accept missing preimage",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: nil,
},
},
invState: invpkg.ContractAccepted,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: nil,
},
},
expErr: invpkg.ErrHTLCPreimageMissing,
},
{
name: "AMP accept invalid preimage",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &fakePreimage,
},
},
invState: invpkg.ContractAccepted,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &fakePreimage,
},
},
expErr: invpkg.ErrHTLCPreimageMismatch,
},
{
name: "AMP accept valid preimage",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
invState: invpkg.ContractAccepted,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
expErr: nil,
},
{
name: "AMP accept valid preimage different htlc set",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
invState: invpkg.ContractAccepted,
setID: &diffSetID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
expErr: nil,
},
{
name: "AMP settle missing preimage",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: nil,
},
},
invState: invpkg.ContractSettled,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: nil,
},
},
expErr: invpkg.ErrHTLCPreimageMissing,
},
{
name: "AMP settle invalid preimage",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &fakePreimage,
},
},
invState: invpkg.ContractSettled,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &fakePreimage,
},
},
expErr: invpkg.ErrHTLCPreimageMismatch,
},
{
name: "AMP settle valid preimage",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
invState: invpkg.ContractSettled,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testNow,
Expiry: 40,
State: invpkg.HtlcStateSettled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
expErr: nil,
},
{
// With the newer AMP logic, this is now valid, as we
// want to be able to accept multiple settle attempts
// to a given pay_addr. In this case, the HTLC should
// remain in the accepted state.
name: "AMP settle valid preimage different htlc set",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
invState: invpkg.ContractSettled,
setID: &diffSetID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
expErr: nil,
},
{
name: "accept invoice htlc already settled",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testAlreadyNow,
Expiry: 40,
State: invpkg.HtlcStateSettled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
invState: invpkg.ContractAccepted,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testAlreadyNow,
Expiry: 40,
State: invpkg.HtlcStateSettled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
expErr: invpkg.ErrHTLCAlreadySettled,
},
{
name: "cancel invoice htlc already settled",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testAlreadyNow,
Expiry: 40,
State: invpkg.HtlcStateSettled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
invState: invpkg.ContractCanceled,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testAlreadyNow,
Expiry: 40,
State: invpkg.HtlcStateSettled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
expErr: invpkg.ErrHTLCAlreadySettled,
},
{
name: "settle invoice htlc already settled",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testAlreadyNow,
Expiry: 40,
State: invpkg.HtlcStateSettled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
invState: invpkg.ContractSettled,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testAlreadyNow,
Expiry: 40,
State: invpkg.HtlcStateSettled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
expErr: nil,
},
{
name: "cancel invoice",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: time.Time{},
Expiry: 40,
State: invpkg.HtlcStateAccepted,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
invState: invpkg.ContractCanceled,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testNow,
Expiry: 40,
State: invpkg.HtlcStateCanceled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
expErr: nil,
},
{
name: "accept invoice htlc already canceled",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testAlreadyNow,
Expiry: 40,
State: invpkg.HtlcStateCanceled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
invState: invpkg.ContractAccepted,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testAlreadyNow,
Expiry: 40,
State: invpkg.HtlcStateCanceled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
expErr: nil,
},
{
name: "cancel invoice htlc already canceled",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testAlreadyNow,
Expiry: 40,
State: invpkg.HtlcStateCanceled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
invState: invpkg.ContractCanceled,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testAlreadyNow,
Expiry: 40,
State: invpkg.HtlcStateCanceled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
expErr: nil,
},
{
name: "settle invoice htlc already canceled",
input: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testAlreadyNow,
Expiry: 40,
State: invpkg.HtlcStateCanceled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
invState: invpkg.ContractSettled,
setID: &setID,
output: invpkg.InvoiceHTLC{
Amt: 5000,
MppTotalAmt: 5000,
AcceptHeight: 100,
AcceptTime: testNow,
ResolveTime: testAlreadyNow,
Expiry: 40,
State: invpkg.HtlcStateCanceled,
CustomRecords: make(record.CustomSet),
AMP: &invpkg.InvoiceHtlcAMPData{
Record: *ampRecord,
Hash: hash,
Preimage: &preimage,
},
},
expErr: nil,
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
testUpdateHTLC(t, test)
})
}
}
func testUpdateHTLC(t *testing.T, test updateHTLCTest) {
htlc := test.input.Copy()
stateChanged, state, err := getUpdatedHtlcState(
htlc, test.invState, test.setID,
)
if stateChanged {
htlc.State = state
htlc.ResolveTime = testNow
}
require.Equal(t, test.expErr, err)
require.Equal(t, test.output, *htlc)
}
// TestDeleteInvoices tests that deleting a list of invoices will succeed
// if all delete references are valid, or will fail otherwise.
func TestDeleteInvoices(t *testing.T) {