mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 09:53:54 +01:00
ffd355c6c4
This is added as a TLV record meaning that all the towers currently on disk that don't have this new field will be seen as Active.
167 lines
4.4 KiB
Go
167 lines
4.4 KiB
Go
package wtdb
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
|
"github.com/lightningnetwork/lnd/tlv"
|
|
)
|
|
|
|
// TowerStatus represents the state of the tower as set by the tower client.
|
|
type TowerStatus uint8
|
|
|
|
const (
|
|
// TowerStatusActive is the default state of the tower, and it indicates
|
|
// that this tower should be used to attempt session creation.
|
|
TowerStatusActive TowerStatus = 0
|
|
|
|
// TowerStatusInactive indicates that the tower should not be used to
|
|
// attempt session creation.
|
|
TowerStatusInactive TowerStatus = 1
|
|
)
|
|
|
|
const (
|
|
// TowerStatusTLVType is the TLV type number that will be used to store
|
|
// the tower's status.
|
|
TowerStatusTLVType = tlv.Type(0)
|
|
)
|
|
|
|
// 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
|
|
|
|
// Status is the status of this tower as set by the client.
|
|
Status TowerStatus
|
|
}
|
|
|
|
// 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 address 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
|
|
}
|
|
}
|
|
|
|
// 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 {
|
|
err := WriteElements(w,
|
|
t.IdentityKey,
|
|
t.Addresses,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
status := uint8(t.Status)
|
|
tlvRecords := []tlv.Record{
|
|
tlv.MakePrimitiveRecord(TowerStatusTLVType, &status),
|
|
}
|
|
|
|
tlvStream, err := tlv.NewStream(tlvRecords...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return tlvStream.Encode(w)
|
|
}
|
|
|
|
// 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 {
|
|
err := ReadElements(r,
|
|
&t.IdentityKey,
|
|
&t.Addresses,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var status uint8
|
|
tlvRecords := []tlv.Record{
|
|
tlv.MakePrimitiveRecord(TowerStatusTLVType, &status),
|
|
}
|
|
|
|
tlvStream, err := tlv.NewStream(tlvRecords...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
typeMap, err := tlvStream.DecodeWithParsedTypes(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, ok := typeMap[TowerStatusTLVType]; ok {
|
|
t.Status = TowerStatus(status)
|
|
}
|
|
|
|
return nil
|
|
}
|