wtdb+wtclient: segregate session-key-index reservations by blob-type
This commit introduces a change in the key format used to reserve/lookup session-key-indexes. Currently the reservations are stored under the tower id, however this creates issues when multiple clients are using the same database since only one reservation is permitted per tower. We fix this by appending the blob type to the session-key-index locator. This allows multiple clients to reserve keys for the same tower, but still limits each client to one outstanding reservation. The changes are made in a way such that we fall back to the legacy format if the a reservation under the new format is not found, but only if the blob type matches blob.TypeAltruistCommit, which is so far the only actively deployed blob type.
This commit is contained in:
5 files changed
+161
-39
No files matched your search
@@ -7,11 +7,17 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/watchtower/blob"
|
||||
"github.com/lightningnetwork/lnd/watchtower/wtdb"
|
||||
)
|
||||
|
||||
type towerPK [33]byte
|
||||
|
||||
type keyIndexKey struct {
|
||||
towerID wtdb.TowerID
|
||||
blobType blob.Type
|
||||
}
|
||||
|
||||
// ClientDB is a mock, in-memory database or testing the watchtower client
|
||||
// behavior.
|
||||
type ClientDB struct {
|
||||
@@ -23,8 +29,9 @@ type ClientDB struct {
|
||||
towerIndex map[towerPK]wtdb.TowerID
|
||||
towers map[wtdb.TowerID]*wtdb.Tower
|
||||
|
||||
nextIndex uint32
|
||||
indexes map[wtdb.TowerID]uint32
|
||||
nextIndex uint32
|
||||
indexes map[keyIndexKey]uint32
|
||||
legacyIndexes map[wtdb.TowerID]uint32
|
||||
}
|
||||
|
||||
// NewClientDB initializes a new mock ClientDB.
|
||||
@@ -34,7 +41,8 @@ func NewClientDB() *ClientDB {
|
||||
activeSessions: make(map[wtdb.SessionID]wtdb.ClientSession),
|
||||
towerIndex: make(map[towerPK]wtdb.TowerID),
|
||||
towers: make(map[wtdb.TowerID]*wtdb.Tower),
|
||||
indexes: make(map[wtdb.TowerID]uint32),
|
||||
indexes: make(map[keyIndexKey]uint32),
|
||||
legacyIndexes: make(map[wtdb.TowerID]uint32),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,10 +237,15 @@ func (m *ClientDB) CreateClientSession(session *wtdb.ClientSession) error {
|
||||
return wtdb.ErrClientSessionAlreadyExists
|
||||
}
|
||||
|
||||
key := keyIndexKey{
|
||||
towerID: session.TowerID,
|
||||
blobType: session.Policy.BlobType,
|
||||
}
|
||||
|
||||
// Ensure that a session key index has been reserved for this tower.
|
||||
keyIndex, ok := m.indexes[session.TowerID]
|
||||
if !ok {
|
||||
return wtdb.ErrNoReservedKeyIndex
|
||||
keyIndex, err := m.getSessionKeyIndex(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure that the session's index matches the reserved index.
|
||||
@@ -242,7 +255,10 @@ func (m *ClientDB) CreateClientSession(session *wtdb.ClientSession) error {
|
||||
|
||||
// Remove the key index reservation for this tower. Once committed, this
|
||||
// permits us to create another session with this tower.
|
||||
delete(m.indexes, session.TowerID)
|
||||
delete(m.indexes, key)
|
||||
if key.blobType == blob.TypeAltruistCommit {
|
||||
delete(m.legacyIndexes, key.towerID)
|
||||
}
|
||||
|
||||
m.activeSessions[session.ID] = wtdb.ClientSession{
|
||||
ID: session.ID,
|
||||
@@ -266,21 +282,42 @@ func (m *ClientDB) CreateClientSession(session *wtdb.ClientSession) error {
|
||||
// CreateClientSession is invoked for that tower and index, at which point a new
|
||||
// index for that tower can be reserved. Multiple calls to this method before
|
||||
// CreateClientSession is invoked should return the same index.
|
||||
func (m *ClientDB) NextSessionKeyIndex(towerID wtdb.TowerID) (uint32, error) {
|
||||
func (m *ClientDB) NextSessionKeyIndex(towerID wtdb.TowerID,
|
||||
blobType blob.Type) (uint32, error) {
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if index, ok := m.indexes[towerID]; ok {
|
||||
key := keyIndexKey{
|
||||
towerID: towerID,
|
||||
blobType: blobType,
|
||||
}
|
||||
|
||||
if index, err := m.getSessionKeyIndex(key); err == nil {
|
||||
return index, nil
|
||||
}
|
||||
|
||||
m.nextIndex++
|
||||
index := m.nextIndex
|
||||
m.indexes[towerID] = index
|
||||
m.indexes[key] = index
|
||||
|
||||
return index, nil
|
||||
}
|
||||
|
||||
func (m *ClientDB) getSessionKeyIndex(key keyIndexKey) (uint32, error) {
|
||||
if index, ok := m.indexes[key]; ok {
|
||||
return index, nil
|
||||
}
|
||||
|
||||
if key.blobType == blob.TypeAltruistCommit {
|
||||
if index, ok := m.legacyIndexes[key.towerID]; ok {
|
||||
return index, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, wtdb.ErrNoReservedKeyIndex
|
||||
}
|
||||
|
||||
// CommitUpdate persists the CommittedUpdate provided in the slot for (session,
|
||||
// seqNum). This allows the client to retransmit this update on startup.
|
||||
func (m *ClientDB) CommitUpdate(id *wtdb.SessionID,
|
||||
|
||||
Reference in new issue
Block a user