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:
parent
787986283c
commit
359b2049b6
@ -273,40 +273,53 @@ func New(config *Config) (*TowerClient, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Infof("Using private watchtower %s, offering policy %s",
|
||||
cfg.PrivateTower, cfg.Policy)
|
||||
|
||||
candidateTowers := newTowerListIterator(tower)
|
||||
|
||||
// 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.
|
||||
// Next, load all candidate sessions and towers from the database 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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Reload any towers from disk using the tower IDs contained in each
|
||||
// candidate session. We will also rederive any session keys needed to
|
||||
// be able to communicate with the towers and authenticate session
|
||||
// requests. This prevents us from having to store the private keys on
|
||||
// disk.
|
||||
candidateSessions := make(map[wtdb.SessionID]*wtdb.ClientSession)
|
||||
sessionTowers := make(map[wtdb.TowerID]*wtdb.Tower)
|
||||
for _, s := range sessions {
|
||||
tower, err := cfg.DB.LoadTowerByID(s.TowerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Candidate sessions must be in an active state.
|
||||
if s.Status != wtdb.CSessionActive {
|
||||
continue
|
||||
}
|
||||
|
||||
sessionPriv, err := DeriveSessionKey(
|
||||
cfg.SecretKeyRing, s.KeyIndex,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Reload the tower from disk using the tower ID contained in
|
||||
// each candidate session. We will also rederive any session
|
||||
// keys needed to be able to communicate with the towers and
|
||||
// authenticate session requests. This prevents us from having
|
||||
// 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.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
|
||||
@ -319,8 +332,8 @@ func New(config *Config) (*TowerClient, error) {
|
||||
c := &TowerClient{
|
||||
cfg: cfg,
|
||||
pipeline: newTaskPipeline(),
|
||||
candidateTowers: candidateTowers,
|
||||
candidateSessions: sessions,
|
||||
candidateTowers: newTowerListIterator(candidateTowers...),
|
||||
candidateSessions: candidateSessions,
|
||||
activeSessions: make(sessionQueueSet),
|
||||
summaries: chanSummaries,
|
||||
statTicker: time.NewTicker(DefaultStatInterval),
|
||||
@ -612,12 +625,6 @@ func (c *TowerClient) nextSessionQueue() *sessionQueue {
|
||||
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
|
||||
break
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package wtdb
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
@ -92,6 +94,15 @@ func (t *Tower) LNAddrs() []*lnwire.NetAddress {
|
||||
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
|
||||
// serialized, since it acts as the key.
|
||||
func (t *Tower) Encode(w io.Writer) error {
|
||||
|
Loading…
Reference in New Issue
Block a user