359b2049b6
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.
123 lines
3.6 KiB
Go
123 lines
3.6 KiB
Go
package wtdb
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
|
|
"github.com/btcsuite/btcd/btcec"
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
)
|
|
|
|
// TowerID is a unique 64-bit identifier allocated to each unique watchtower.
|
|
// This allows the client to conserve on-disk space by not needing to always
|
|
// reference towers by their pubkey.
|
|
type TowerID uint64
|
|
|
|
// TowerIDFromBytes constructs a TowerID from the provided byte slice. The
|
|
// argument must have at least 8 bytes, and should contain the TowerID in
|
|
// big-endian byte order.
|
|
func TowerIDFromBytes(towerIDBytes []byte) TowerID {
|
|
return TowerID(byteOrder.Uint64(towerIDBytes))
|
|
}
|
|
|
|
// Bytes encodes a TowerID into an 8-byte slice in big-endian byte order.
|
|
func (id TowerID) Bytes() []byte {
|
|
var buf [8]byte
|
|
byteOrder.PutUint64(buf[:], uint64(id))
|
|
return buf[:]
|
|
}
|
|
|
|
// Tower holds the necessary components required to connect to a remote tower.
|
|
// Communication is handled by brontide, and requires both a public key and an
|
|
// address.
|
|
type Tower struct {
|
|
// ID is a unique ID for this record assigned by the database.
|
|
ID TowerID
|
|
|
|
// IdentityKey is the public key of the remote node, used to
|
|
// authenticate the brontide transport.
|
|
IdentityKey *btcec.PublicKey
|
|
|
|
// Addresses is a list of possible addresses to reach the tower.
|
|
Addresses []net.Addr
|
|
}
|
|
|
|
// AddAddress adds the given address to the tower's in-memory list of addresses.
|
|
// If the address's string is already present, the Tower will be left
|
|
// unmodified. Otherwise, the adddress is prepended to the beginning of the
|
|
// Tower's addresses, on the assumption that it is fresher than the others.
|
|
//
|
|
// NOTE: This method is NOT safe for concurrent use.
|
|
func (t *Tower) AddAddress(addr net.Addr) {
|
|
// Ensure we don't add a duplicate address.
|
|
addrStr := addr.String()
|
|
for _, existingAddr := range t.Addresses {
|
|
if existingAddr.String() == addrStr {
|
|
return
|
|
}
|
|
}
|
|
|
|
// Add this address to the front of the list, on the assumption that it
|
|
// is a fresher address and will be tried first.
|
|
t.Addresses = append([]net.Addr{addr}, t.Addresses...)
|
|
}
|
|
|
|
// RemoveAddress removes the given address from the tower's in-memory list of
|
|
// addresses. If the address doesn't exist, then this will act as a NOP.
|
|
func (t *Tower) RemoveAddress(addr net.Addr) {
|
|
addrStr := addr.String()
|
|
for i, address := range t.Addresses {
|
|
if address.String() != addrStr {
|
|
continue
|
|
}
|
|
t.Addresses = append(t.Addresses[:i], t.Addresses[i+1:]...)
|
|
return
|
|
}
|
|
}
|
|
|
|
// LNAddrs generates a list of lnwire.NetAddress from a Tower instance's
|
|
// addresses. This can be used to have a client try multiple addresses for the
|
|
// same Tower.
|
|
//
|
|
// NOTE: This method is NOT safe for concurrent use.
|
|
func (t *Tower) LNAddrs() []*lnwire.NetAddress {
|
|
addrs := make([]*lnwire.NetAddress, 0, len(t.Addresses))
|
|
for _, addr := range t.Addresses {
|
|
addrs = append(addrs, &lnwire.NetAddress{
|
|
IdentityKey: t.IdentityKey,
|
|
Address: addr,
|
|
})
|
|
}
|
|
|
|
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 {
|
|
return WriteElements(w,
|
|
t.IdentityKey,
|
|
t.Addresses,
|
|
)
|
|
}
|
|
|
|
// Decode reads a Tower from the passed io.Reader. The TowerID is meant to be
|
|
// decoded from the key.
|
|
func (t *Tower) Decode(r io.Reader) error {
|
|
return ReadElements(r,
|
|
&t.IdentityKey,
|
|
&t.Addresses,
|
|
)
|
|
}
|