watchtower: load persisted towers upon TowerClient creation
We do this as a convenience for WatchtowerClient users so that they do not need to re-add towers upon restarts. We ensure not to re-add towers that have been previously removed by determining whether it has any lingering active sessions.
This commit is contained in:
2 files changed
+50
-32
No files matched your search
@@ -273,40 +273,53 @@ func New(config *Config) (*TowerClient, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Using private watchtower %s, offering policy %s",
|
// Next, load all candidate sessions and towers from the database into
|
||||||
cfg.PrivateTower, cfg.Policy)
|
// the client. We will use any of these session if their policies match
|
||||||
|
// the current policy of the client, otherwise they will be ignored and
|
||||||
candidateTowers := newTowerListIterator(tower)
|
// new sessions will be requested.
|
||||||
|
|
||||||
// Next, load all active sessions from the db into the client. We will
|
|
||||||
// use any of these session if their policies match the current policy
|
|
||||||
// of the client, otherwise they will be ignored and new sessions will
|
|
||||||
// be requested.
|
|
||||||
sessions, err := cfg.DB.ListClientSessions(nil)
|
sessions, err := cfg.DB.ListClientSessions(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload any towers from disk using the tower IDs contained in each
|
candidateSessions := make(map[wtdb.SessionID]*wtdb.ClientSession)
|
||||||
// candidate session. We will also rederive any session keys needed to
|
sessionTowers := make(map[wtdb.TowerID]*wtdb.Tower)
|
||||||
// be able to communicate with the towers and authenticate session
|
|
||||||
// requests. This prevents us from having to store the private keys on
|
|
||||||
// disk.
|
|
||||||
for _, s := range sessions {
|
for _, s := range sessions {
|
||||||
tower, err := cfg.DB.LoadTowerByID(s.TowerID)
|
// Candidate sessions must be in an active state.
|
||||||
if err != nil {
|
if s.Status != wtdb.CSessionActive {
|
||||||
return nil, err
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionPriv, err := DeriveSessionKey(
|
// Reload the tower from disk using the tower ID contained in
|
||||||
cfg.SecretKeyRing, s.KeyIndex,
|
// each candidate session. We will also rederive any session
|
||||||
)
|
// keys needed to be able to communicate with the towers and
|
||||||
if err != nil {
|
// authenticate session requests. This prevents us from having
|
||||||
return nil, err
|
// to store the private keys on disk.
|
||||||
|
tower, ok := sessionTowers[s.TowerID]
|
||||||
|
if !ok {
|
||||||
|
var err error
|
||||||
|
tower, err = cfg.DB.LoadTowerByID(s.TowerID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Tower = tower
|
s.Tower = tower
|
||||||
s.SessionPrivKey = sessionPriv
|
|
||||||
|
sessionKey, err := DeriveSessionKey(cfg.SecretKeyRing, s.KeyIndex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s.SessionPrivKey = sessionKey
|
||||||
|
|
||||||
|
candidateSessions[s.ID] = s
|
||||||
|
sessionTowers[tower.ID] = tower
|
||||||
|
}
|
||||||
|
|
||||||
|
var candidateTowers []*wtdb.Tower
|
||||||
|
for _, tower := range sessionTowers {
|
||||||
|
log.Infof("Using private watchtower %s, offering policy %s",
|
||||||
|
tower, cfg.Policy)
|
||||||
|
candidateTowers = append(candidateTowers, tower)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the sweep pkscripts that have been generated for all previously
|
// Load the sweep pkscripts that have been generated for all previously
|
||||||
@@ -319,8 +332,8 @@ func New(config *Config) (*TowerClient, error) {
|
|||||||
c := &TowerClient{
|
c := &TowerClient{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
pipeline: newTaskPipeline(),
|
pipeline: newTaskPipeline(),
|
||||||
candidateTowers: candidateTowers,
|
candidateTowers: newTowerListIterator(candidateTowers...),
|
||||||
candidateSessions: sessions,
|
candidateSessions: candidateSessions,
|
||||||
activeSessions: make(sessionQueueSet),
|
activeSessions: make(sessionQueueSet),
|
||||||
summaries: chanSummaries,
|
summaries: chanSummaries,
|
||||||
statTicker: time.NewTicker(DefaultStatInterval),
|
statTicker: time.NewTicker(DefaultStatInterval),
|
||||||
@@ -612,12 +625,6 @@ func (c *TowerClient) nextSessionQueue() *sessionQueue {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip any sessions that are still active, but are not for the
|
|
||||||
// users currently configured tower.
|
|
||||||
if !c.candidateTowers.IsActive(sessionInfo.TowerID) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
candidateSession = sessionInfo
|
candidateSession = sessionInfo
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package wtdb
|
package wtdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
@@ -92,6 +94,15 @@ func (t *Tower) LNAddrs() []*lnwire.NetAddress {
|
|||||||
return addrs
|
return addrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a user-friendly identifier of the tower.
|
||||||
|
func (t *Tower) String() string {
|
||||||
|
pubKey := hex.EncodeToString(t.IdentityKey.SerializeCompressed())
|
||||||
|
if len(t.Addresses) == 0 {
|
||||||
|
return pubKey
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%v@%v", pubKey, t.Addresses[0])
|
||||||
|
}
|
||||||
|
|
||||||
// Encode writes the Tower to the passed io.Writer. The TowerID is not
|
// Encode writes the Tower to the passed io.Writer. The TowerID is not
|
||||||
// serialized, since it acts as the key.
|
// serialized, since it acts as the key.
|
||||||
func (t *Tower) Encode(w io.Writer) error {
|
func (t *Tower) Encode(w io.Writer) error {
|
||||||
|
|||||||
Reference in new issue
Block a user