• 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

0.0
/lntest/mock/spendnotifier.go
1
package mock
2

3
import (
4
        "sync"
5

6
        "github.com/btcsuite/btcd/wire"
7
        "github.com/lightningnetwork/lnd/chainntnfs"
8
)
9

10
// SpendNotifier extends the mock.ChainNotifier so that spend
11
// notifications can be triggered and delivered to subscribers.
12
type SpendNotifier struct {
13
        *ChainNotifier
14
        spendMap map[wire.OutPoint][]chan *chainntnfs.SpendDetail
15
        spends   map[wire.OutPoint]*chainntnfs.SpendDetail
16
        mtx      sync.Mutex
17
}
18

19
// MakeMockSpendNotifier creates a SpendNotifier.
UNCOV
20
func MakeMockSpendNotifier() *SpendNotifier {
×
UNCOV
21
        return &SpendNotifier{
×
UNCOV
22
                ChainNotifier: &ChainNotifier{
×
UNCOV
23
                        SpendChan: make(chan *chainntnfs.SpendDetail),
×
UNCOV
24
                        EpochChan: make(chan *chainntnfs.BlockEpoch),
×
UNCOV
25
                        ConfChan:  make(chan *chainntnfs.TxConfirmation),
×
UNCOV
26
                },
×
UNCOV
27
                spendMap: make(map[wire.OutPoint][]chan *chainntnfs.SpendDetail),
×
UNCOV
28
                spends:   make(map[wire.OutPoint]*chainntnfs.SpendDetail),
×
UNCOV
29
        }
×
UNCOV
30
}
×
31

32
// RegisterSpendNtfn registers a spend notification for a specified outpoint.
33
func (s *SpendNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
UNCOV
34
        _ []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) {
×
UNCOV
35

×
UNCOV
36
        s.mtx.Lock()
×
UNCOV
37
        defer s.mtx.Unlock()
×
UNCOV
38

×
UNCOV
39
        spendChan := make(chan *chainntnfs.SpendDetail, 1)
×
UNCOV
40
        if detail, ok := s.spends[*outpoint]; ok {
×
41
                // Deliver spend immediately if details are already known.
×
42
                spendChan <- &chainntnfs.SpendDetail{
×
43
                        SpentOutPoint:     detail.SpentOutPoint,
×
44
                        SpendingHeight:    detail.SpendingHeight,
×
45
                        SpendingTx:        detail.SpendingTx,
×
46
                        SpenderTxHash:     detail.SpenderTxHash,
×
47
                        SpenderInputIndex: detail.SpenderInputIndex,
×
48
                }
×
UNCOV
49
        } else {
×
UNCOV
50
                // Otherwise, queue the notification for delivery if the spend
×
UNCOV
51
                // is ever received.
×
UNCOV
52
                s.spendMap[*outpoint] = append(s.spendMap[*outpoint], spendChan)
×
UNCOV
53
        }
×
54

UNCOV
55
        return &chainntnfs.SpendEvent{
×
UNCOV
56
                Spend:  spendChan,
×
UNCOV
57
                Cancel: func() {},
×
58
        }, nil
59
}
60

61
// Spend dispatches SpendDetails to all subscribers of the outpoint. The details
62
// will includethe transaction and height provided by the caller.
63
func (s *SpendNotifier) Spend(outpoint *wire.OutPoint, height int32,
UNCOV
64
        txn *wire.MsgTx) {
×
UNCOV
65

×
UNCOV
66
        s.mtx.Lock()
×
UNCOV
67
        defer s.mtx.Unlock()
×
UNCOV
68

×
UNCOV
69
        var inputIndex uint32
×
UNCOV
70
        for i, in := range txn.TxIn {
×
UNCOV
71
                if in.PreviousOutPoint == *outpoint {
×
UNCOV
72
                        inputIndex = uint32(i)
×
UNCOV
73
                }
×
74
        }
75

UNCOV
76
        txnHash := txn.TxHash()
×
UNCOV
77
        details := &chainntnfs.SpendDetail{
×
UNCOV
78
                SpentOutPoint:     outpoint,
×
UNCOV
79
                SpendingHeight:    height,
×
UNCOV
80
                SpendingTx:        txn,
×
UNCOV
81
                SpenderTxHash:     &txnHash,
×
UNCOV
82
                SpenderInputIndex: inputIndex,
×
UNCOV
83
        }
×
UNCOV
84

×
UNCOV
85
        // Cache details in case of late registration.
×
UNCOV
86
        if _, ok := s.spends[*outpoint]; !ok {
×
UNCOV
87
                s.spends[*outpoint] = details
×
UNCOV
88
        }
×
89

90
        // Deliver any backlogged spend notifications.
UNCOV
91
        if spendChans, ok := s.spendMap[*outpoint]; ok {
×
UNCOV
92
                delete(s.spendMap, *outpoint)
×
UNCOV
93
                for _, spendChan := range spendChans {
×
UNCOV
94
                        spendChan <- &chainntnfs.SpendDetail{
×
UNCOV
95
                                SpentOutPoint:     details.SpentOutPoint,
×
UNCOV
96
                                SpendingHeight:    details.SpendingHeight,
×
UNCOV
97
                                SpendingTx:        details.SpendingTx,
×
UNCOV
98
                                SpenderTxHash:     details.SpenderTxHash,
×
UNCOV
99
                                SpenderInputIndex: details.SpenderInputIndex,
×
UNCOV
100
                        }
×
UNCOV
101
                }
×
102
        }
103
}
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