forked from lightningnetwork/lnd
-
Notifications
You must be signed in to change notification settings - Fork 24
/
peers.go
129 lines (108 loc) · 3.21 KB
/
peers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package channeldb
import (
"bytes"
"errors"
"time"
"github.com/decred/dcrlnd/kvdb"
"github.com/decred/dcrlnd/routing/route"
)
var (
// peersBucket is the name of a top level bucket in which we store
// information about our peers. Information for different peers is
// stored in buckets keyed by their public key.
//
//
// peers-bucket
// |
// |-- <peer-pubkey>
// | |--flap-count-key: <ts><flap count>
// |
// |-- <peer-pubkey>
// | |--flap-count-key: <ts><flap count>
//
// Note(decred): each peer has an additional value set:
// |--last-gossip-msg-ts: <ts>
peersBucket = []byte("peers-bucket")
// flapCountKey is a key used in the peer pubkey sub-bucket that stores
// the timestamp of a peer's last flap count and its all time flap
// count.
flapCountKey = []byte("flap-count")
)
var (
// ErrNoPeerBucket is returned when we try to read entries for a peer
// that is not tracked.
ErrNoPeerBucket = errors.New("peer bucket not found")
)
// FlapCount contains information about a peer's flap count.
type FlapCount struct {
// Count provides the total flap count for a peer.
Count uint32
// LastFlap is the timestamp of the last flap recorded for a peer.
LastFlap time.Time
}
// WriteFlapCounts writes the flap count for a set of peers to disk, creating a
// bucket for the peer's pubkey if necessary. Note that this function overwrites
// the current value.
func (d *DB) WriteFlapCounts(flapCounts map[route.Vertex]*FlapCount) error {
return kvdb.Update(d, func(tx kvdb.RwTx) error {
// Run through our set of flap counts and record them for
// each peer, creating a bucket for the peer pubkey if required.
for peer, flapCount := range flapCounts {
peers := tx.ReadWriteBucket(peersBucket)
peerBucket, err := peers.CreateBucketIfNotExists(
peer[:],
)
if err != nil {
return err
}
var b bytes.Buffer
err = serializeTime(&b, flapCount.LastFlap)
if err != nil {
return err
}
if err = WriteElement(&b, flapCount.Count); err != nil {
return err
}
err = peerBucket.Put(flapCountKey, b.Bytes())
if err != nil {
return err
}
}
return nil
}, func() {})
}
// ReadFlapCount attempts to read the flap count for a peer, failing if the
// peer is not found or we do not have flap count stored.
func (d *DB) ReadFlapCount(pubkey route.Vertex) (*FlapCount, error) {
var flapCount FlapCount
if err := kvdb.View(d, func(tx kvdb.RTx) error {
peers := tx.ReadBucket(peersBucket)
peerBucket := peers.NestedReadBucket(pubkey[:])
if peerBucket == nil {
return ErrNoPeerBucket
}
flapBytes := peerBucket.Get(flapCountKey)
if flapBytes == nil {
// Note(decred): in lnd this returns an opaque error,
// but we may have entries in the peersBucket that
// may not have a set flapCountKey, so return the same
// error that flags that the info does not exist for
// this peer.
return ErrNoPeerBucket
}
var (
err error
r = bytes.NewReader(flapBytes)
)
flapCount.LastFlap, err = deserializeTime(r)
if err != nil {
return err
}
return ReadElements(r, &flapCount.Count)
}, func() {
flapCount = FlapCount{}
}); err != nil {
return nil, err
}
return &flapCount, nil
}