multi: make payment clocks configurable

Thread lnd clocks through the client and instant out state machine. The
production default remains the wall clock while tests can inject
deterministic time.
This commit is contained in:
Boris Nagaev 2026-08-08 17:42:20 -05:00
parent 8b79e52e60
commit 2225538201
No known key found for this signature in database
5 changed files with 22 additions and 3 deletions

View file

@ -204,6 +204,7 @@ func NewClient(dbDir string, loopDB loopdb.SwapStore,
},
AssetClient: cfg.AssetClient,
LoopOutMaxParts: cfg.LoopOutMaxParts,
Clock: clock.NewDefaultClock(),
}
sweeper := &sweep.Sweeper{
@ -489,7 +490,7 @@ func (s *Client) resumeSwaps(ctx context.Context,
swapCfg := newSwapConfig(
s.lndServices, s.Store, s.Server, s.AssetClient,
clock.NewDefaultClock(),
s.Clock,
)
for _, pend := range loopOutSwaps {
@ -583,7 +584,7 @@ func (s *Client) LoopOut(globalCtx context.Context,
// Create a new swap object for this swap.
swapCfg := newSwapConfig(
s.lndServices, s.Store, s.Server, s.AssetClient,
clock.NewDefaultClock(),
s.Clock,
)
initResult, err := newLoopOutSwap(
@ -767,7 +768,7 @@ func (s *Client) LoopIn(globalCtx context.Context,
initiationHeight := s.executor.height()
swapCfg := newSwapConfig(
s.lndServices, s.Store, s.Server, s.AssetClient,
clock.NewDefaultClock(),
s.Clock,
)
initResult, err := newLoopInSwap(
globalCtx, swapCfg, initiationHeight, request,

View file

@ -7,6 +7,7 @@ import (
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop/assets"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightningnetwork/lnd/clock"
"google.golang.org/grpc"
)
@ -20,4 +21,5 @@ type clientConfig struct {
L402Store l402.Store
CreateExpiryTimer func(expiry time.Duration) <-chan time.Time
LoopOutMaxParts uint32
Clock clock.Clock
}

View file

@ -8,6 +8,7 @@ import (
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop/fsm"
"github.com/lightninglabs/loop/swapserverrpc"
"github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/input"
)
@ -170,6 +171,9 @@ type Config struct {
// Network is the network that is used for the swap.
Network *chaincfg.Params
// Clock provides the current time.
Clock clock.Clock
}
// FSM is the state machine that handles the instant out.
@ -183,6 +187,9 @@ type FSM struct {
// InstantOut contains all the information about the instant out.
InstantOut *InstantOut
// clck provides the current time.
clck clock.Clock
// htlcMusig2Sessions contains all the reservations input musig2
// sessions that will be used for the htlc transaction.
htlcMusig2Sessions []*input.MuSig2SessionInfo
@ -205,9 +212,15 @@ func NewFSM(cfg *Config, protocolVersion ProtocolVersion) (*FSM, error) {
// NewFSMFromInstantOut creates a new instantout FSM from an existing instantout
// recovered from the database.
func NewFSMFromInstantOut(cfg *Config, instantOut *InstantOut) (*FSM, error) {
fsmClock := cfg.Clock
if fsmClock == nil {
fsmClock = clock.NewDefaultClock()
}
instantOutFSM := &FSM{
cfg: cfg,
InstantOut: instantOut,
clck: fsmClock,
}
switch instantOut.protocolVersion {
case ProtocolVersionFullReservation:

View file

@ -783,6 +783,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
ReservationManager: reservationManager,
InstantOutClient: instantOutClient,
Network: d.lnd.ChainParams,
Clock: clock.NewDefaultClock(),
}
instantOutManager = instantout.NewInstantOutManager(

View file

@ -16,6 +16,7 @@ import (
"github.com/lightninglabs/loop/sweepbatcher"
"github.com/lightninglabs/loop/test"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/stretchr/testify/require"
@ -139,6 +140,7 @@ func createClientTestContext(t *testing.T,
Server: serverMock,
Store: store,
CreateExpiryTimer: timerFactory,
Clock: clock.NewTestClock(testTime),
})
statusChan := make(chan SwapInfo)