forked from lightningnetwork/lnd
-
Notifications
You must be signed in to change notification settings - Fork 24
/
gossiper.go
101 lines (84 loc) · 2.85 KB
/
gossiper.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
package channeldb
import (
"bytes"
"errors"
"fmt"
"time"
"github.com/btcsuite/btcwallet/walletdb"
"github.com/decred/dcrlnd/kvdb"
"github.com/decred/dcrlnd/routing/route"
)
var (
// peerLastGossipMsgTSKey is the key for a value in the peer bucket that
// tracks the unix timestamp of the last received gossip message
// (ChannelUpdate, ChannelAnnouncement, NodeAnnounce).
peerLastGossipMsgTSKey = []byte("last-gossip-msg-ts")
// ErrNoPeerLastGossipMsgTS is returned when there are no recorded
// gossip msg timestamps for a peer.
ErrNoPeerLastGossipMsgTS = errors.New("last gossip msg ts not recorded")
// ErrOutdatedLastGossipMsgTS is returned when an attempt is made to
// store a gossip timestamp that is before the previously stored one.
ErrOutdatedLastGossipMsgTS = errors.New("last gossip msg ts specified " +
"is older than previously recorded ts")
)
// readPeerLastGossipMsgTS reads and deserializes the last gossip msg timestamp
// for a given peer.
func readPeerLastGossipMsgTS(rootPeersBucket walletdb.ReadBucket, peer route.Vertex) (time.Time, error) {
var ts time.Time
peerBucket := rootPeersBucket.NestedReadBucket(peer[:])
if peerBucket == nil {
return ts, fmt.Errorf("%w for peer %v",
ErrNoPeerLastGossipMsgTS, peer)
}
tsBytes := peerBucket.Get(peerLastGossipMsgTSKey)
if tsBytes == nil {
return ts, fmt.Errorf("%w for peer %v",
ErrNoPeerLastGossipMsgTS, peer)
}
r := bytes.NewReader(tsBytes)
return deserializeTime(r)
}
// UpdatePeerLastGossipMsgTS stores the specified timestamp as the timestamp of
// the most recent gossip message received from the specified peer. If this
// timestamp is older than a previously stored timestamp, this function returns
// an error.
func (d *DB) UpdatePeerLastGossipMsgTS(peer route.Vertex, ts time.Time) error {
return kvdb.Update(d, func(tx kvdb.RwTx) error {
peers := tx.ReadWriteBucket(peersBucket)
// Read existing ts. Error is ignored here, because an empty
// time equals 0.
prevTS, _ := readPeerLastGossipMsgTS(peers, peer)
if ts.Before(prevTS) {
return fmt.Errorf("%w: %s is before %s",
ErrOutdatedLastGossipMsgTS, ts, prevTS)
}
peerBucket, err := peers.CreateBucketIfNotExists(
peer[:],
)
if err != nil {
return err
}
var b bytes.Buffer
err = serializeTime(&b, ts)
if err != nil {
return err
}
err = peerBucket.Put(peerLastGossipMsgTSKey, b.Bytes())
if err != nil {
return err
}
return nil
}, func() {})
}
// ReadPeerLastGossipMsgTS returns the timestamp stored as most recent for
// a gossip message received from the specified peer.
func (d *DB) ReadPeerLastGossipMsgTS(peer route.Vertex) (time.Time, error) {
var ts time.Time
err := kvdb.View(d, func(tx kvdb.RTx) error {
peers := tx.ReadBucket(peersBucket)
var err error
ts, err = readPeerLastGossipMsgTS(peers, peer)
return err
}, func() { ts = time.Time{} })
return ts, err
}