Skip to content

Commit 82bfaa0

Browse files
committed
reservation: add client requested reservations to manager
1 parent 86b5490 commit 82bfaa0

File tree

2 files changed

+103
-9
lines changed

2 files changed

+103
-9
lines changed

instantout/reservation/manager.go

Lines changed: 102 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,21 @@ import (
1010
"github.com/btcsuite/btcd/btcec/v2"
1111
"github.com/btcsuite/btcd/btcutil"
1212
"github.com/lightninglabs/loop/fsm"
13+
"github.com/lightninglabs/loop/swapserverrpc"
1314
reservationrpc "github.com/lightninglabs/loop/swapserverrpc"
1415
)
1516

17+
var (
18+
defaultWaitForStateTime = time.Second * 15
19+
)
20+
21+
// FSMSendEventReq contains the information needed to send an event to the FSM.
22+
type FSMSendEventReq struct {
23+
fsm *FSM
24+
event fsm.EventType
25+
eventCtx fsm.EventContext
26+
}
27+
1628
// Manager manages the reservation state machines.
1729
type Manager struct {
1830
// cfg contains all the services that the reservation manager needs to
@@ -22,6 +34,10 @@ type Manager struct {
2234
// activeReservations contains all the active reservationsFSMs.
2335
activeReservations map[ID]*FSM
2436

37+
currentHeight int32
38+
39+
reqChan chan *FSMSendEventReq
40+
2541
sync.Mutex
2642
}
2743

@@ -30,6 +46,7 @@ func NewManager(cfg *Config) *Manager {
3046
return &Manager{
3147
cfg: cfg,
3248
activeReservations: make(map[ID]*FSM),
49+
reqChan: make(chan *FSMSendEventReq),
3350
}
3451
}
3552

@@ -42,7 +59,7 @@ func (m *Manager) Run(ctx context.Context, height int32,
4259
runCtx, cancel := context.WithCancel(ctx)
4360
defer cancel()
4461

45-
currentHeight := height
62+
m.currentHeight = height
4663

4764
err := m.RecoverReservations(runCtx)
4865
if err != nil {
@@ -64,7 +81,9 @@ func (m *Manager) Run(ctx context.Context, height int32,
6481
select {
6582
case height := <-newBlockChan:
6683
log.Debugf("Received block %v", height)
67-
currentHeight = height
84+
m.Lock()
85+
m.currentHeight = height
86+
m.Unlock()
6887

6988
case reservationRes, ok := <-ntfnChan:
7089
if !ok {
@@ -76,13 +95,26 @@ func (m *Manager) Run(ctx context.Context, height int32,
7695

7796
log.Debugf("Received reservation %x",
7897
reservationRes.ReservationId)
79-
_, err := m.newReservation(
80-
runCtx, uint32(currentHeight), reservationRes,
98+
_, err := m.newReservationFromNtfn(
99+
runCtx, uint32(m.currentHeight), reservationRes,
81100
)
82101
if err != nil {
83102
return err
84103
}
85104

105+
case req := <-m.reqChan:
106+
// We'll send the event in a goroutine to avoid blocking
107+
// the main loop.
108+
go func() {
109+
err := req.fsm.SendEvent(
110+
runCtx, req.event, req.eventCtx,
111+
)
112+
if err != nil {
113+
log.Errorf("Error sending event: %v",
114+
err)
115+
}
116+
}()
117+
86118
case err := <-newBlockErrChan:
87119
return err
88120

@@ -93,9 +125,11 @@ func (m *Manager) Run(ctx context.Context, height int32,
93125
}
94126
}
95127

96-
// newReservation creates a new reservation from the reservation request.
97-
func (m *Manager) newReservation(ctx context.Context, currentHeight uint32,
98-
req *reservationrpc.ServerReservationNotification) (*FSM, error) {
128+
// newReservationFromNtfn creates a new reservation from the reservation
129+
// notification.
130+
func (m *Manager) newReservationFromNtfn(ctx context.Context,
131+
currentHeight uint32, req *reservationrpc.ServerReservationNotification,
132+
) (*FSM, error) {
99133

100134
var reservationID ID
101135
err := reservationID.FromByteSlice(
@@ -120,7 +154,7 @@ func (m *Manager) newReservation(ctx context.Context, currentHeight uint32,
120154
m.activeReservations[reservationID] = reservationFSM
121155
m.Unlock()
122156

123-
initContext := &InitReservationContext{
157+
initContext := &ServerRequestedInitContext{
124158
reservationID: reservationID,
125159
serverPubkey: serverKey,
126160
value: btcutil.Amount(req.Value),
@@ -154,6 +188,66 @@ func (m *Manager) newReservation(ctx context.Context, currentHeight uint32,
154188
return reservationFSM, nil
155189
}
156190

191+
// RequestReservationFromServer sends a request to the server to create a new
192+
// reservation.
193+
func (m *Manager) RequestReservationFromServer(ctx context.Context,
194+
value btcutil.Amount, expiry uint32, maxPrepaymentAmt btcutil.Amount) (
195+
*Reservation, error) {
196+
197+
m.Lock()
198+
currentHeight := m.currentHeight
199+
m.Unlock()
200+
// Create a new reservation req.
201+
req := &ClientRequestedInitContext{
202+
value: value,
203+
relativeExpiry: expiry,
204+
heightHint: uint32(currentHeight),
205+
maxPrepaymentAmt: maxPrepaymentAmt,
206+
}
207+
208+
reservationFSM := NewFSM(m.cfg, ProtocolVersionClientInitiated)
209+
// Send the event to the main loop.
210+
m.reqChan <- &FSMSendEventReq{
211+
fsm: reservationFSM,
212+
event: OnClientInitialized,
213+
eventCtx: req,
214+
}
215+
216+
// We'll now wait for the reservation to be in the state where we are
217+
// sending the prepayment.
218+
err := reservationFSM.DefaultObserver.WaitForState(
219+
ctx, defaultWaitForStateTime, SendPrepaymentPayment,
220+
fsm.WithAbortEarlyOnErrorOption(),
221+
)
222+
if err != nil {
223+
return nil, err
224+
}
225+
226+
// Now we can add the reservation to our active fsm.
227+
m.Lock()
228+
m.activeReservations[reservationFSM.reservation.ID] = reservationFSM
229+
m.Unlock()
230+
231+
return reservationFSM.reservation, nil
232+
}
233+
234+
// QuoteReservation quotes the server for a new reservation.
235+
func (m *Manager) QuoteReservation(ctx context.Context, value btcutil.Amount,
236+
expiry uint32) (btcutil.Amount, error) {
237+
238+
quoteReq := &swapserverrpc.QuoteReservationRequest{
239+
Value: uint64(value),
240+
Expiry: expiry,
241+
}
242+
243+
req, err := m.cfg.ReservationClient.QuoteReservation(ctx, quoteReq)
244+
if err != nil {
245+
return 0, err
246+
}
247+
248+
return btcutil.Amount(req.PrepayCost), nil
249+
}
250+
157251
// RecoverReservations tries to recover all reservations that are still active
158252
// from the database.
159253
func (m *Manager) RecoverReservations(ctx context.Context) error {

instantout/reservation/manager_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func TestManager(t *testing.T) {
3737
<-initChan
3838

3939
// Create a new reservation.
40-
reservationFSM, err := testContext.manager.newReservation(
40+
reservationFSM, err := testContext.manager.newReservationFromNtfn(
4141
ctxb, uint32(testContext.mockLnd.Height),
4242
&swapserverrpc.ServerReservationNotification{
4343
ReservationId: defaultReservationId[:],

0 commit comments

Comments
 (0)