package wtdb import ( "errors" "net" "sync" "github.com/btcsuite/btcd/btcec" "github.com/lightningnetwork/lnd/lnwire" ) var ( // ErrTowerNotFound signals that the target tower was not found in the // database. ErrTowerNotFound = errors.New("tower not found") ) // 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 mu sync.RWMutex } // 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. func (t *Tower) AddAddress(addr net.Addr) { t.mu.Lock() defer t.mu.Unlock() // 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...) } // 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. func (t *Tower) LNAddrs() []*lnwire.NetAddress { t.mu.RLock() defer t.mu.RUnlock() 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 }