mirror of
https://github.com/lightninglabs/loop
synced 2024-11-09 19:10:47 +00:00
f40ef193e9
Previously we may have stored negative costs for some loop out swaps which this commit attempts to correct by fetching all completed swap, calculating the correct costs and overriding them in the database.
185 lines
5.6 KiB
Go
185 lines
5.6 KiB
Go
package loop
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/btcutil"
|
|
"github.com/lightninglabs/lndclient"
|
|
"github.com/lightninglabs/loop/loopdb"
|
|
"github.com/lightninglabs/loop/test"
|
|
"github.com/lightningnetwork/lnd/lntypes"
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestCalculateLoopOutCost tests the CalculateLoopOutCost function.
|
|
func TestCalculateLoopOutCost(t *testing.T) {
|
|
// Set up test context objects.
|
|
lnd := test.NewMockLnd()
|
|
server := newServerMock(lnd)
|
|
store := loopdb.NewStoreMock(t)
|
|
|
|
cfg := &swapConfig{
|
|
lnd: &lnd.LndServices,
|
|
store: store,
|
|
server: server,
|
|
}
|
|
|
|
height := int32(600)
|
|
req := *testRequest
|
|
initResult, err := newLoopOutSwap(
|
|
context.Background(), cfg, height, &req,
|
|
)
|
|
require.NoError(t, err)
|
|
swap, err := store.FetchLoopOutSwap(
|
|
context.Background(), initResult.swap.hash,
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
// Override the chain cost so it's negative.
|
|
const expectedChainCost = btcutil.Amount(1000)
|
|
|
|
// Now we have the swap and prepay invoices so let's calculate the
|
|
// costs without providing the payments first, so we don't account for
|
|
// any routing fees.
|
|
paymentFees := make(map[lntypes.Hash]lnwire.MilliSatoshi)
|
|
_, err = CalculateLoopOutCost(lnd.ChainParams, swap, paymentFees)
|
|
|
|
// We expect that the call fails as the swap isn't finished yet.
|
|
require.Error(t, err)
|
|
|
|
// Override the swap state to make it look like the swap is finished
|
|
// and make the chain cost negative too, so we can test that it'll be
|
|
// corrected to be positive in the cost calculation.
|
|
swap.Events = append(
|
|
swap.Events, &loopdb.LoopEvent{
|
|
SwapStateData: loopdb.SwapStateData{
|
|
State: loopdb.StateSuccess,
|
|
Cost: loopdb.SwapCost{
|
|
Onchain: -expectedChainCost,
|
|
},
|
|
},
|
|
},
|
|
)
|
|
costs, err := CalculateLoopOutCost(lnd.ChainParams, swap, paymentFees)
|
|
require.NoError(t, err)
|
|
|
|
expectedServerCost := server.swapInvoiceAmt + server.prepayInvoiceAmt -
|
|
swap.Contract.AmountRequested
|
|
require.Equal(t, expectedServerCost, costs.Server)
|
|
require.Equal(t, btcutil.Amount(0), costs.Offchain)
|
|
require.Equal(t, expectedChainCost, costs.Onchain)
|
|
|
|
// Now add the two payments to the payments map and calculate the costs
|
|
// again. We expect that the routng fees are now accounted for.
|
|
paymentFees[server.swapHash] = lnwire.NewMSatFromSatoshis(44)
|
|
paymentFees[server.prepayHash] = lnwire.NewMSatFromSatoshis(11)
|
|
|
|
costs, err = CalculateLoopOutCost(lnd.ChainParams, swap, paymentFees)
|
|
require.NoError(t, err)
|
|
|
|
expectedOffchainCost := btcutil.Amount(44 + 11)
|
|
require.Equal(t, expectedServerCost, costs.Server)
|
|
require.Equal(t, expectedOffchainCost, costs.Offchain)
|
|
require.Equal(t, expectedChainCost, costs.Onchain)
|
|
|
|
// Now override the last update to make the swap timed out at the HTLC
|
|
// sweep. We expect that the chain cost won't change, and only the
|
|
// prepay will be accounted for.
|
|
swap.Events[0] = &loopdb.LoopEvent{
|
|
SwapStateData: loopdb.SwapStateData{
|
|
State: loopdb.StateFailSweepTimeout,
|
|
Cost: loopdb.SwapCost{
|
|
Onchain: 0,
|
|
},
|
|
},
|
|
}
|
|
|
|
costs, err = CalculateLoopOutCost(lnd.ChainParams, swap, paymentFees)
|
|
require.NoError(t, err)
|
|
|
|
expectedServerCost = server.prepayInvoiceAmt
|
|
expectedOffchainCost = btcutil.Amount(11)
|
|
require.Equal(t, expectedServerCost, costs.Server)
|
|
require.Equal(t, expectedOffchainCost, costs.Offchain)
|
|
require.Equal(t, btcutil.Amount(0), costs.Onchain)
|
|
}
|
|
|
|
// TestCostMigration tests the cost migration for loop out swaps.
|
|
func TestCostMigration(t *testing.T) {
|
|
// Set up test context objects.
|
|
lnd := test.NewMockLnd()
|
|
server := newServerMock(lnd)
|
|
store := loopdb.NewStoreMock(t)
|
|
|
|
cfg := &swapConfig{
|
|
lnd: &lnd.LndServices,
|
|
store: store,
|
|
server: server,
|
|
}
|
|
|
|
height := int32(600)
|
|
req := *testRequest
|
|
initResult, err := newLoopOutSwap(
|
|
context.Background(), cfg, height, &req,
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
// Override the chain cost so it's negative.
|
|
const expectedChainCost = btcutil.Amount(1000)
|
|
|
|
// Override the swap state to make it look like the swap is finished
|
|
// and make the chain cost negative too, so we can test that it'll be
|
|
// corrected to be positive in the cost calculation.
|
|
err = store.UpdateLoopOut(
|
|
context.Background(), initResult.swap.hash, time.Now(),
|
|
loopdb.SwapStateData{
|
|
State: loopdb.StateSuccess,
|
|
Cost: loopdb.SwapCost{
|
|
Onchain: -expectedChainCost,
|
|
},
|
|
},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
// Add the two mocked payment to LND. Note that we only care about the
|
|
// fees here, so we don't need to provide the full payment details.
|
|
lnd.Payments = []lndclient.Payment{
|
|
{
|
|
Hash: server.swapHash,
|
|
Fee: lnwire.NewMSatFromSatoshis(44),
|
|
},
|
|
{
|
|
Hash: server.prepayHash,
|
|
Fee: lnwire.NewMSatFromSatoshis(11),
|
|
},
|
|
}
|
|
|
|
// Now we can run the migration.
|
|
err = MigrateLoopOutCosts(context.Background(), lnd.LndServices, store)
|
|
require.NoError(t, err)
|
|
|
|
// Finally check that the swap cost has been updated correctly.
|
|
swap, err := store.FetchLoopOutSwap(
|
|
context.Background(), initResult.swap.hash,
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
expectedServerCost := server.swapInvoiceAmt + server.prepayInvoiceAmt -
|
|
swap.Contract.AmountRequested
|
|
|
|
costs := swap.Events[0].Cost
|
|
expectedOffchainCost := btcutil.Amount(44 + 11)
|
|
require.Equal(t, expectedServerCost, costs.Server)
|
|
require.Equal(t, expectedOffchainCost, costs.Offchain)
|
|
require.Equal(t, expectedChainCost, costs.Onchain)
|
|
|
|
// Now run the migration again to make sure it doesn't fail. This also
|
|
// indicates that the migration did not run the second time as
|
|
// otherwise the store mocks SetMigration function would fail.
|
|
err = MigrateLoopOutCosts(context.Background(), lnd.LndServices, store)
|
|
require.NoError(t, err)
|
|
}
|