mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
staticaddr/loopin: factor invoice update handling
Extract the monitor invoice update semantics into a helper and cover the existing state mapping with a dedicated test.
This commit is contained in:
parent
ee5d84b323
commit
a6d061c568
2 changed files with 110 additions and 22 deletions
|
|
@ -359,6 +359,35 @@ func (f *FSM) cancelSwapInvoice() {
|
|||
}
|
||||
}
|
||||
|
||||
// handleInvoiceUpdate applies the monitor state's invoice-update semantics and
|
||||
// reports whether the update produced a terminal event.
|
||||
func (f *FSM) handleInvoiceUpdate(update lndclient.InvoiceUpdate) (
|
||||
fsm.EventType, bool) {
|
||||
|
||||
switch update.State {
|
||||
case invoices.ContractOpen:
|
||||
return fsm.NoOp, false
|
||||
|
||||
case invoices.ContractAccepted:
|
||||
return fsm.NoOp, false
|
||||
|
||||
case invoices.ContractSettled:
|
||||
f.Debugf("received off-chain payment update %v", update.State)
|
||||
return OnPaymentReceived, true
|
||||
|
||||
case invoices.ContractCanceled:
|
||||
// If the invoice was canceled we only log here since we still need
|
||||
// to monitor until the htlc timed out.
|
||||
log.Warnf("invoice for swap hash %v canceled", f.loopIn.SwapHash)
|
||||
return fsm.NoOp, false
|
||||
|
||||
default:
|
||||
err := fmt.Errorf("unexpected invoice state %v for swap hash %v "+
|
||||
"canceled", update.State, f.loopIn.SwapHash)
|
||||
return f.HandleError(err), true
|
||||
}
|
||||
}
|
||||
|
||||
// SignHtlcTxAction is called if the htlc was initialized and the server
|
||||
// provided the necessary information to construct the htlc tx. We sign the htlc
|
||||
// tx and send the signatures to the server.
|
||||
|
|
@ -737,28 +766,8 @@ func (f *FSM) MonitorInvoiceAndHtlcTxAction(ctx context.Context,
|
|||
return f.HandleError(err)
|
||||
|
||||
case update := <-invoiceUpdateChan:
|
||||
switch update.State {
|
||||
case invoices.ContractOpen:
|
||||
case invoices.ContractAccepted:
|
||||
case invoices.ContractSettled:
|
||||
f.Debugf("received off-chain payment update "+
|
||||
"%v", update.State)
|
||||
|
||||
return OnPaymentReceived
|
||||
|
||||
case invoices.ContractCanceled:
|
||||
// If the invoice was canceled we only log here
|
||||
// since we still need to monitor until the htlc
|
||||
// timed out.
|
||||
log.Warnf("invoice for swap hash %v canceled",
|
||||
f.loopIn.SwapHash)
|
||||
|
||||
default:
|
||||
err = fmt.Errorf("unexpected invoice state %v "+
|
||||
"for swap hash %v canceled",
|
||||
update.State, f.loopIn.SwapHash)
|
||||
|
||||
return f.HandleError(err)
|
||||
if event, done := f.handleInvoiceUpdate(update); done {
|
||||
return event
|
||||
}
|
||||
|
||||
case err = <-invoiceErrChan:
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package loopin
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -24,6 +25,84 @@ import (
|
|||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// TestHandleInvoiceUpdate verifies that invoice state updates map to the
|
||||
// monitor events expected by the static address loop-in FSM.
|
||||
func TestHandleInvoiceUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
swapHash := lntypes.Hash{1, 2, 3}
|
||||
tests := []struct {
|
||||
name string
|
||||
state invoices.ContractState
|
||||
event fsm.EventType
|
||||
done bool
|
||||
errString string
|
||||
}{
|
||||
{
|
||||
name: "open",
|
||||
state: invoices.ContractOpen,
|
||||
event: fsm.NoOp,
|
||||
},
|
||||
{
|
||||
name: "accepted",
|
||||
state: invoices.ContractAccepted,
|
||||
event: fsm.NoOp,
|
||||
},
|
||||
{
|
||||
name: "settled",
|
||||
state: invoices.ContractSettled,
|
||||
event: OnPaymentReceived,
|
||||
done: true,
|
||||
},
|
||||
{
|
||||
name: "canceled",
|
||||
state: invoices.ContractCanceled,
|
||||
event: fsm.NoOp,
|
||||
},
|
||||
{
|
||||
name: "unexpected",
|
||||
state: invoices.ContractState(99),
|
||||
event: fsm.OnError,
|
||||
done: true,
|
||||
errString: "unexpected invoice state",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
f := &FSM{
|
||||
StateMachine: &fsm.StateMachine{},
|
||||
loopIn: &StaticAddressLoopIn{
|
||||
SwapHash: swapHash,
|
||||
},
|
||||
}
|
||||
|
||||
event, done := f.handleInvoiceUpdate(
|
||||
lndclient.InvoiceUpdate{
|
||||
Invoice: lndclient.Invoice{
|
||||
State: test.state,
|
||||
},
|
||||
},
|
||||
)
|
||||
require.Equal(t, test.event, event)
|
||||
require.Equal(t, test.done, done)
|
||||
|
||||
if test.errString == "" {
|
||||
require.Nil(t, f.LastActionError)
|
||||
} else {
|
||||
require.ErrorContains(
|
||||
t, f.LastActionError, test.errString,
|
||||
)
|
||||
require.ErrorContains(
|
||||
t, f.LastActionError, fmt.Sprint(swapHash),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestMonitorInvoiceAndHtlcTxReRegistersOnConfErr ensures that an error from
|
||||
// the HTLC confirmation subscription triggers a re-registration. Without the
|
||||
// regression fix, only the initial registration would be performed and the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue