• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 14193549836

01 Apr 2025 10:40AM UTC coverage: 69.046% (+0.007%) from 69.039%
14193549836

Pull #9665

github

web-flow
Merge e8825f209 into b01f4e514
Pull Request #9665: kvdb: bump etcd libs to v3.5.12

133439 of 193262 relevant lines covered (69.05%)

22119.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.78
/watchtower/wtdb/tower.go
1
package wtdb
2

3
import (
4
        "encoding/hex"
5
        "fmt"
6
        "io"
7
        "net"
8

9
        "github.com/btcsuite/btcd/btcec/v2"
10
        "github.com/lightningnetwork/lnd/tlv"
11
)
12

13
// TowerStatus represents the state of the tower as set by the tower client.
14
type TowerStatus uint8
15

16
const (
17
        // TowerStatusActive is the default state of the tower, and it indicates
18
        // that this tower should be used to attempt session creation.
19
        TowerStatusActive TowerStatus = 0
20

21
        // TowerStatusInactive indicates that the tower should not be used to
22
        // attempt session creation.
23
        TowerStatusInactive TowerStatus = 1
24
)
25

26
const (
27
        // TowerStatusTLVType is the TLV type number that will be used to store
28
        // the tower's status.
29
        TowerStatusTLVType = tlv.Type(0)
30
)
31

32
// TowerID is a unique 64-bit identifier allocated to each unique watchtower.
33
// This allows the client to conserve on-disk space by not needing to always
34
// reference towers by their pubkey.
35
type TowerID uint64
36

37
// TowerIDFromBytes constructs a TowerID from the provided byte slice. The
38
// argument must have at least 8 bytes, and should contain the TowerID in
39
// big-endian byte order.
40
func TowerIDFromBytes(towerIDBytes []byte) TowerID {
233✔
41
        return TowerID(byteOrder.Uint64(towerIDBytes))
233✔
42
}
233✔
43

44
// Bytes encodes a TowerID into an 8-byte slice in big-endian byte order.
45
func (id TowerID) Bytes() []byte {
1,054✔
46
        var buf [8]byte
1,054✔
47
        byteOrder.PutUint64(buf[:], uint64(id))
1,054✔
48
        return buf[:]
1,054✔
49
}
1,054✔
50

51
// Tower holds the necessary components required to connect to a remote tower.
52
// Communication is handled by brontide, and requires both a public key and an
53
// address.
54
type Tower struct {
55
        // ID is a unique ID for this record assigned by the database.
56
        ID TowerID
57

58
        // IdentityKey is the public key of the remote node, used to
59
        // authenticate the brontide transport.
60
        IdentityKey *btcec.PublicKey
61

62
        // Addresses is a list of possible addresses to reach the tower.
63
        Addresses []net.Addr
64

65
        // Status is the status of this tower as set by the client.
66
        Status TowerStatus
67
}
68

69
// AddAddress adds the given address to the tower's in-memory list of addresses.
70
// If the address's string is already present, the Tower will be left
71
// unmodified. Otherwise, the address is prepended to the beginning of the
72
// Tower's addresses, on the assumption that it is fresher than the others.
73
//
74
// NOTE: This method is NOT safe for concurrent use.
75
func (t *Tower) AddAddress(addr net.Addr) {
24✔
76
        // Ensure we don't add a duplicate address.
24✔
77
        addrStr := addr.String()
24✔
78
        for _, existingAddr := range t.Addresses {
48✔
79
                if existingAddr.String() == addrStr {
42✔
80
                        return
18✔
81
                }
18✔
82
        }
83

84
        // Add this address to the front of the list, on the assumption that it
85
        // is a fresher address and will be tried first.
86
        t.Addresses = append([]net.Addr{addr}, t.Addresses...)
6✔
87
}
88

89
// RemoveAddress removes the given address from the tower's in-memory list of
90
// addresses. If the address doesn't exist, then this will act as a NOP.
91
func (t *Tower) RemoveAddress(addr net.Addr) {
6✔
92
        addrStr := addr.String()
6✔
93
        for i, address := range t.Addresses {
13✔
94
                if address.String() != addrStr {
8✔
95
                        continue
1✔
96
                }
97
                t.Addresses = append(t.Addresses[:i], t.Addresses[i+1:]...)
6✔
98
                return
6✔
99
        }
100
}
101

102
// String returns a user-friendly identifier of the tower.
103
func (t *Tower) String() string {
×
104
        pubKey := hex.EncodeToString(t.IdentityKey.SerializeCompressed())
×
105
        if len(t.Addresses) == 0 {
×
106
                return pubKey
×
107
        }
×
108
        return fmt.Sprintf("%v@%v", pubKey, t.Addresses[0])
×
109
}
110

111
// Encode writes the Tower to the passed io.Writer. The TowerID is not
112
// serialized, since it acts as the key.
113
func (t *Tower) Encode(w io.Writer) error {
206✔
114
        err := WriteElements(w,
206✔
115
                t.IdentityKey,
206✔
116
                t.Addresses,
206✔
117
        )
206✔
118
        if err != nil {
206✔
119
                return err
×
120
        }
×
121

122
        status := uint8(t.Status)
206✔
123
        tlvRecords := []tlv.Record{
206✔
124
                tlv.MakePrimitiveRecord(TowerStatusTLVType, &status),
206✔
125
        }
206✔
126

206✔
127
        tlvStream, err := tlv.NewStream(tlvRecords...)
206✔
128
        if err != nil {
206✔
129
                return err
×
130
        }
×
131

132
        return tlvStream.Encode(w)
206✔
133
}
134

135
// Decode reads a Tower from the passed io.Reader. The TowerID is meant to be
136
// decoded from the key.
137
func (t *Tower) Decode(r io.Reader) error {
317✔
138
        err := ReadElements(r,
317✔
139
                &t.IdentityKey,
317✔
140
                &t.Addresses,
317✔
141
        )
317✔
142
        if err != nil {
317✔
143
                return err
×
144
        }
×
145

146
        var status uint8
317✔
147
        tlvRecords := []tlv.Record{
317✔
148
                tlv.MakePrimitiveRecord(TowerStatusTLVType, &status),
317✔
149
        }
317✔
150

317✔
151
        tlvStream, err := tlv.NewStream(tlvRecords...)
317✔
152
        if err != nil {
317✔
153
                return err
×
154
        }
×
155

156
        typeMap, err := tlvStream.DecodeWithParsedTypes(r)
317✔
157
        if err != nil {
317✔
158
                return err
×
159
        }
×
160

161
        if _, ok := typeMap[TowerStatusTLVType]; ok {
634✔
162
                t.Status = TowerStatus(status)
317✔
163
        }
317✔
164

165
        return nil
317✔
166
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc