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

lightningnetwork / lnd / 15561477203

10 Jun 2025 01:54PM UTC coverage: 58.351% (-10.1%) from 68.487%
15561477203

Pull #9356

github

web-flow
Merge 6440b25db into c6d6d4c0b
Pull Request #9356: lnrpc: add incoming/outgoing channel ids filter to forwarding history request

33 of 36 new or added lines in 2 files covered. (91.67%)

28366 existing lines in 455 files now uncovered.

97715 of 167461 relevant lines covered (58.35%)

1.81 hits per line

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

73.02
/chainntnfs/best_block_view.go
1
package chainntnfs
2

3
import (
4
        "errors"
5
        "fmt"
6
        "sync"
7
        "sync/atomic"
8

9
        "github.com/btcsuite/btcd/wire"
10
)
11

12
// BestBlockView is an interface that allows the querying of the most
13
// up-to-date blockchain state with low overhead. Valid implementations of this
14
// interface must track the latest chain state.
15
type BestBlockView interface {
16
        // BestHeight gets the most recent block height known to the view.
17
        BestHeight() (uint32, error)
18

19
        // BestBlockHeader gets the most recent block header known to the view.
20
        BestBlockHeader() (*wire.BlockHeader, error)
21
}
22

23
// BestBlockTracker is a tiny subsystem that tracks the blockchain tip
24
// and saves the most recent tip information in memory for querying. It is a
25
// valid implementation of BestBlockView and additionally includes
26
// methods for starting and stopping the system.
27
type BestBlockTracker struct {
28
        notifier        ChainNotifier
29
        blockNtfnStream *BlockEpochEvent
30
        current         atomic.Pointer[BlockEpoch]
31
        mu              sync.Mutex
32
        quit            chan struct{}
33
        wg              sync.WaitGroup
34
}
35

36
// This is a compile time check to ensure that BestBlockTracker implements
37
// BestBlockView.
38
var _ BestBlockView = (*BestBlockTracker)(nil)
39

40
// NewBestBlockTracker creates a new BestBlockTracker that isn't running yet.
41
// It will not provide up to date information unless it has been started. The
42
// ChainNotifier parameter must also be started prior to starting the
43
// BestBlockTracker.
44
func NewBestBlockTracker(chainNotifier ChainNotifier) *BestBlockTracker {
3✔
45
        return &BestBlockTracker{
3✔
46
                notifier:        chainNotifier,
3✔
47
                blockNtfnStream: nil,
3✔
48
                quit:            make(chan struct{}),
3✔
49
        }
3✔
50
}
3✔
51

52
// BestHeight gets the most recent block height known to the
53
// BestBlockTracker.
54
func (t *BestBlockTracker) BestHeight() (uint32, error) {
3✔
55
        epoch := t.current.Load()
3✔
56
        if epoch == nil {
3✔
57
                return 0, errors.New("best block height not yet known")
×
58
        }
×
59

60
        return uint32(epoch.Height), nil
3✔
61
}
62

63
// BestBlockHeader gets the most recent block header known to the
64
// BestBlockTracker.
UNCOV
65
func (t *BestBlockTracker) BestBlockHeader() (*wire.BlockHeader, error) {
×
UNCOV
66
        epoch := t.current.Load()
×
UNCOV
67
        if epoch == nil {
×
68
                return nil, errors.New("best block header not yet known")
×
69
        }
×
70

UNCOV
71
        return epoch.BlockHeader, nil
×
72
}
73

74
// updateLoop is a helper that subscribes to the underlying BlockEpochEvent
75
// stream and updates the internal values to match the new BlockEpochs that
76
// are discovered.
77
//
78
// MUST be run as a goroutine.
79
func (t *BestBlockTracker) updateLoop() {
3✔
80
        defer t.wg.Done()
3✔
81
        for {
6✔
82
                select {
3✔
83
                case epoch, ok := <-t.blockNtfnStream.Epochs:
3✔
84
                        if !ok {
6✔
85
                                Log.Error("dead epoch stream in " +
3✔
86
                                        "BestBlockTracker")
3✔
87

3✔
88
                                return
3✔
89
                        }
3✔
90
                        t.current.Store(epoch)
3✔
UNCOV
91
                case <-t.quit:
×
UNCOV
92
                        t.current.Store(nil)
×
UNCOV
93
                        return
×
94
                }
95
        }
96
}
97

98
// Start starts the BestBlockTracker. It is an error to start it if it
99
// is already started.
100
func (t *BestBlockTracker) Start() error {
3✔
101
        t.mu.Lock()
3✔
102
        defer t.mu.Unlock()
3✔
103

3✔
104
        if t.blockNtfnStream != nil {
3✔
105
                return fmt.Errorf("BestBlockTracker is already started")
×
106
        }
×
107

108
        var err error
3✔
109
        t.blockNtfnStream, err = t.notifier.RegisterBlockEpochNtfn(nil)
3✔
110
        if err != nil {
3✔
111
                return err
×
112
        }
×
113

114
        t.wg.Add(1)
3✔
115
        go t.updateLoop()
3✔
116

3✔
117
        return nil
3✔
118
}
119

120
// Stop stops the BestBlockTracker. It is an error to stop it if it has
121
// not been started or if it has already been stopped.
122
func (t *BestBlockTracker) Stop() error {
3✔
123
        t.mu.Lock()
3✔
124
        defer t.mu.Unlock()
3✔
125

3✔
126
        if t.blockNtfnStream == nil {
3✔
127
                return fmt.Errorf("BestBlockTracker is not running")
×
128
        }
×
129
        close(t.quit)
3✔
130
        t.wg.Wait()
3✔
131
        t.blockNtfnStream.Cancel()
3✔
132
        t.blockNtfnStream = nil
3✔
133

3✔
134
        return nil
3✔
135
}
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