Skip to content

Commit 6765707

Browse files
committed
session+lnrpc: add StateReserved and delete these on start up
1 parent 56915d4 commit 6765707

File tree

8 files changed

+200
-32
lines changed

8 files changed

+200
-32
lines changed

litrpc/lit-autopilot.swagger.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,8 @@
662662
"STATE_CREATED",
663663
"STATE_IN_USE",
664664
"STATE_REVOKED",
665-
"STATE_EXPIRED"
665+
"STATE_EXPIRED",
666+
"STATE_RESERVED"
666667
],
667668
"default": "STATE_CREATED"
668669
},

litrpc/lit-sessions.pb.go

Lines changed: 33 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

litrpc/lit-sessions.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ enum SessionState {
9797
STATE_IN_USE = 1;
9898
STATE_REVOKED = 2;
9999
STATE_EXPIRED = 3;
100+
STATE_RESERVED = 4;
100101
}
101102

102103
message AddSessionResponse {

litrpc/lit-sessions.swagger.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,8 @@
521521
"STATE_CREATED",
522522
"STATE_IN_USE",
523523
"STATE_REVOKED",
524-
"STATE_EXPIRED"
524+
"STATE_EXPIRED",
525+
"STATE_RESERVED"
525526
],
526527
"default": "STATE_CREATED"
527528
},

session/interface.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ const (
5151
// StateExpired is the state of a session that has passed its expiry
5252
// date.
5353
StateExpired State = 3
54+
55+
// StateReserved is a temporary initial state of a session. On start-up,
56+
// any sessions in this state should be cleaned up.
57+
//
58+
// NOTE: this isn't used yet.
59+
StateReserved State = 4
5460
)
5561

5662
// MacaroonRecipe defines the permissions and caveats that should be used
@@ -213,5 +219,9 @@ type Store interface {
213219
CheckSessionGroupPredicate(groupID ID,
214220
fn func(s *Session) bool) (bool, error)
215221

222+
// DeleteReservedSessions deletes all sessions that are in the
223+
// StateReserved state.
224+
DeleteReservedSessions() error
225+
216226
IDToGroupIndex
217227
}

session/kvdb_store.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,99 @@ func (db *BoltStore) listSessions(filterFn func(s *Session) bool) ([]*Session, e
437437
return sessions, nil
438438
}
439439

440+
// DeleteReservedSessions deletes all sessions that are in the StateReserved
441+
// state.
442+
//
443+
// NOTE: this is part of the Store interface.
444+
func (db *DB) DeleteReservedSessions() error {
445+
return db.Update(func(tx *bbolt.Tx) error {
446+
sessionBucket, err := getBucket(tx, sessionBucketKey)
447+
if err != nil {
448+
return err
449+
}
450+
451+
return sessionBucket.ForEach(func(k, v []byte) error {
452+
// We'll also get buckets here, skip those (identified
453+
// by nil value).
454+
if v == nil {
455+
return nil
456+
}
457+
458+
session, err := DeserializeSession(bytes.NewReader(v))
459+
if err != nil {
460+
return err
461+
}
462+
463+
if session.State != StateReserved {
464+
return nil
465+
}
466+
467+
err = sessionBucket.Delete(k)
468+
if err != nil {
469+
return err
470+
}
471+
472+
idIndexBkt := sessionBucket.Bucket(idIndexKey)
473+
if idIndexBkt == nil {
474+
return ErrDBInitErr
475+
}
476+
477+
// Delete the entire session ID bucket.
478+
err = idIndexBkt.DeleteBucket(session.ID[:])
479+
if err != nil {
480+
return err
481+
}
482+
483+
groupIdIndexBkt := sessionBucket.Bucket(groupIDIndexKey)
484+
if groupIdIndexBkt == nil {
485+
return ErrDBInitErr
486+
}
487+
488+
groupBkt := groupIdIndexBkt.Bucket(session.GroupID[:])
489+
if groupBkt == nil {
490+
return ErrDBInitErr
491+
}
492+
493+
sessionIDsBkt := groupBkt.Bucket(sessionIDKey)
494+
if sessionIDsBkt == nil {
495+
return ErrDBInitErr
496+
}
497+
498+
var (
499+
seqKey []byte
500+
numSessions int
501+
)
502+
err = sessionIDsBkt.ForEach(func(k, v []byte) error {
503+
numSessions++
504+
505+
if !bytes.Equal(v, session.ID[:]) {
506+
return nil
507+
}
508+
509+
seqKey = k
510+
511+
return nil
512+
})
513+
if err != nil {
514+
return err
515+
}
516+
517+
if numSessions == 0 {
518+
return fmt.Errorf("no sessions found for "+
519+
"group ID %x", session.GroupID)
520+
}
521+
522+
if numSessions == 1 {
523+
// Delete the whole group bucket.
524+
return groupBkt.DeleteBucket(sessionIDKey)
525+
}
526+
527+
// Else, delete just the session ID entry.
528+
return sessionIDsBkt.Delete(seqKey)
529+
})
530+
})
531+
}
532+
440533
// RevokeSession updates the state of the session with the given local
441534
// public key to be revoked.
442535
//

session/store_test.go

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,52 @@ func TestBasicSessionStore(t *testing.T) {
137137
assertEqualSessions(t, s2, sessions[1])
138138
assertEqualSessions(t, s3, sessions[2])
139139

140-
sessions, err = db.ListSessions(StateInUse)
140+
sessions, err = db.ListSessions(StateReserved)
141141
require.NoError(t, err)
142142
require.Empty(t, sessions)
143+
144+
// Demonstrate deletion of a reserved session.
145+
//
146+
// Calling DeleteReservedSessions should have no effect yet since none
147+
// of the sessions are reserved.
148+
require.NoError(t, db.DeleteReservedSessions())
149+
150+
sessions, err = db.ListSessions(StateReserved)
151+
require.NoError(t, err)
152+
require.Empty(t, sessions)
153+
154+
// Add a session and put it in the StateReserved state.
155+
s5 := newSession(t, db, clock, "session 5", withState(StateReserved))
156+
require.NoError(t, db.CreateSession(s5))
157+
158+
sessions, err = db.ListSessions(StateReserved)
159+
require.NoError(t, err)
160+
require.Equal(t, 1, len(sessions))
161+
assertEqualSessions(t, s5, sessions[0])
162+
163+
// Show that the group ID/session ID index has also been populated with
164+
// this session.
165+
groupID, err := db.GetGroupID(s5.ID)
166+
require.NoError(t, err)
167+
require.Equal(t, s5.ID, groupID)
168+
169+
sessIDs, err := db.GetSessionIDs(s5.GroupID)
170+
require.NoError(t, err)
171+
require.Equal(t, []ID{s5.ID}, sessIDs)
172+
173+
// Now delete the reserved session and show that it is no longer in the
174+
// database and no longer in the group ID/session ID index.
175+
require.NoError(t, db.DeleteReservedSessions())
176+
177+
sessions, err = db.ListSessions(StateReserved)
178+
require.NoError(t, err)
179+
require.Empty(t, sessions)
180+
181+
groupID, err = db.GetGroupID(s5.ID)
182+
require.ErrorContains(t, err, "no index entry")
183+
184+
sessIDs, err = db.GetSessionIDs(s5.GroupID)
185+
require.ErrorContains(t, err, "no sessions for group ID")
143186
}
144187

145188
// TestLinkingSessions tests that session linking works as expected.
@@ -354,6 +397,12 @@ func withType(t Type) testSessionModifier {
354397
}
355398
}
356399

400+
func withState(state State) testSessionModifier {
401+
return func(s *Session) {
402+
s.State = state
403+
}
404+
}
405+
357406
func newSession(t *testing.T, db Store, clock clock.Clock, label string,
358407
mods ...testSessionModifier) *Session {
359408

session_rpcserver.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ func newSessionRPCServer(cfg *sessionRpcServerConfig) (*sessionRpcServer,
100100
// start all the components necessary for the sessionRpcServer to start serving
101101
// requests. This includes resuming all non-revoked sessions.
102102
func (s *sessionRpcServer) start(ctx context.Context) error {
103+
// Delete all sessions in the Reserved state.
104+
err := s.cfg.db.DeleteReservedSessions()
105+
if err != nil {
106+
return fmt.Errorf("error deleting reserved sessions: %v", err)
107+
}
108+
103109
// Start up all previously created sessions.
104110
sessions, err := s.cfg.db.ListSessions(
105111
session.StateCreated,
@@ -1519,6 +1525,9 @@ func marshalRPCMacaroonRecipe(
15191525
// marshalRPCState converts a session state to its RPC counterpart.
15201526
func marshalRPCState(state session.State) (litrpc.SessionState, error) {
15211527
switch state {
1528+
case session.StateReserved:
1529+
return litrpc.SessionState_STATE_RESERVED, nil
1530+
15221531
case session.StateCreated:
15231532
return litrpc.SessionState_STATE_CREATED, nil
15241533

0 commit comments

Comments
 (0)