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

lightningnetwork / lnd / 13211764208

08 Feb 2025 03:08AM UTC coverage: 49.288% (-9.5%) from 58.815%
13211764208

Pull #9489

github

calvinrzachman
itest: verify switchrpc server enforces send then track

We prevent the rpc server from allowing onion dispatches for
attempt IDs which have already been tracked by rpc clients.

This helps protect the client from leaking a duplicate onion
attempt. NOTE: This is not the only method for solving this
issue! The issue could be addressed via careful client side
programming which accounts for the uncertainty and async
nature of dispatching onions to a remote process via RPC.
This would require some lnd ChannelRouter changes for how
we intend to use these RPCs though.
Pull Request #9489: multi: add BuildOnion, SendOnion, and TrackOnion RPCs

474 of 990 new or added lines in 11 files covered. (47.88%)

27321 existing lines in 435 files now uncovered.

101192 of 205306 relevant lines covered (49.29%)

1.54 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