• 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
/chainntnfs/test_utils.go
1
//go:build dev
2
// +build dev
3

4
package chainntnfs
5

6
import (
7
        "errors"
8
        "fmt"
9
        "testing"
10
        "time"
11

12
        "github.com/btcsuite/btcd/btcec/v2"
13
        "github.com/btcsuite/btcd/btcjson"
14
        "github.com/btcsuite/btcd/btcutil"
15
        "github.com/btcsuite/btcd/chaincfg/chainhash"
16
        "github.com/btcsuite/btcd/integration/rpctest"
17
        "github.com/btcsuite/btcd/txscript"
18
        "github.com/btcsuite/btcd/wire"
19
        "github.com/lightningnetwork/lnd/input"
20
        "github.com/lightningnetwork/lnd/lntest/unittest"
21
        "github.com/stretchr/testify/require"
22
)
23

24
var (
25
        // TrickleInterval is the interval at which the miner should trickle
26
        // transactions to its peers. We'll set it small to ensure the miner
27
        // propagates transactions quickly in the tests.
28
        TrickleInterval = 10 * time.Millisecond
29
)
30

31
// randPubKeyHashScript generates a P2PKH script that pays to the public key of
32
// a randomly-generated private key.
UNCOV
33
func randPubKeyHashScript() ([]byte, *btcec.PrivateKey, error) {
×
UNCOV
34
        privKey, err := btcec.NewPrivateKey()
×
UNCOV
35
        if err != nil {
×
36
                return nil, nil, err
×
37
        }
×
38

UNCOV
39
        pubKeyHash := btcutil.Hash160(privKey.PubKey().SerializeCompressed())
×
UNCOV
40
        addrScript, err := btcutil.NewAddressWitnessPubKeyHash(
×
UNCOV
41
                pubKeyHash, unittest.NetParams,
×
UNCOV
42
        )
×
UNCOV
43
        if err != nil {
×
44
                return nil, nil, err
×
45
        }
×
46

UNCOV
47
        pkScript, err := txscript.PayToAddrScript(addrScript)
×
UNCOV
48
        if err != nil {
×
49
                return nil, nil, err
×
50
        }
×
51

UNCOV
52
        return pkScript, privKey, nil
×
53
}
54

55
// GetTestTxidAndScript generate a new test transaction and returns its txid and
56
// the script of the output being generated.
UNCOV
57
func GetTestTxidAndScript(h *rpctest.Harness) (*chainhash.Hash, []byte, error) {
×
UNCOV
58
        pkScript, _, err := randPubKeyHashScript()
×
UNCOV
59
        if err != nil {
×
60
                return nil, nil, fmt.Errorf("unable to generate pkScript: %w",
×
61
                        err)
×
62
        }
×
UNCOV
63
        output := &wire.TxOut{Value: 2e8, PkScript: pkScript}
×
UNCOV
64
        txid, err := h.SendOutputs([]*wire.TxOut{output}, 10)
×
UNCOV
65
        if err != nil {
×
66
                return nil, nil, err
×
67
        }
×
68

UNCOV
69
        return txid, pkScript, nil
×
70
}
71

72
// WaitForMempoolTx waits for the txid to be seen in the miner's mempool.
UNCOV
73
func WaitForMempoolTx(miner *rpctest.Harness, txid *chainhash.Hash) error {
×
UNCOV
74
        timeout := time.After(10 * time.Second)
×
UNCOV
75
        trickle := time.After(2 * TrickleInterval)
×
UNCOV
76
        for {
×
UNCOV
77
                // Check for the harness' knowledge of the txid.
×
UNCOV
78
                tx, err := miner.Client.GetRawTransaction(txid)
×
UNCOV
79
                if err != nil {
×
80
                        jsonErr, ok := err.(*btcjson.RPCError)
×
81
                        if ok && jsonErr.Code == btcjson.ErrRPCNoTxInfo {
×
82
                                continue
×
83
                        }
84
                        return err
×
85
                }
86

UNCOV
87
                if tx != nil && tx.Hash().IsEqual(txid) {
×
UNCOV
88
                        break
×
89
                }
90

91
                select {
×
92
                case <-time.After(100 * time.Millisecond):
×
93
                case <-timeout:
×
94
                        return errors.New("timed out waiting for tx")
×
95
                }
96
        }
97

98
        // To ensure any transactions propagate from the miner to the peers
99
        // before returning, ensure we have waited for at least
100
        // 2*trickleInterval before returning.
UNCOV
101
        select {
×
UNCOV
102
        case <-trickle:
×
103
        case <-timeout:
×
104
                return errors.New("timeout waiting for trickle interval. " +
×
105
                        "Trickle interval to large?")
×
106
        }
107

UNCOV
108
        return nil
×
109
}
110

111
// CreateSpendableOutput creates and returns an output that can be spent later
112
// on.
113
func CreateSpendableOutput(t *testing.T,
UNCOV
114
        miner *rpctest.Harness) (*wire.OutPoint, *wire.TxOut, *btcec.PrivateKey) {
×
UNCOV
115

×
UNCOV
116
        t.Helper()
×
UNCOV
117

×
UNCOV
118
        // Create a transaction that only has one output, the one destined for
×
UNCOV
119
        // the recipient.
×
UNCOV
120
        pkScript, privKey, err := randPubKeyHashScript()
×
UNCOV
121
        require.NoError(t, err, "unable to generate pkScript")
×
UNCOV
122
        output := &wire.TxOut{Value: 2e8, PkScript: pkScript}
×
UNCOV
123
        txid, err := miner.SendOutputsWithoutChange([]*wire.TxOut{output}, 10)
×
UNCOV
124
        require.NoError(t, err, "unable to create tx")
×
UNCOV
125

×
UNCOV
126
        // Mine the transaction to mark the output as spendable.
×
UNCOV
127
        if err := WaitForMempoolTx(miner, txid); err != nil {
×
128
                t.Fatalf("tx not relayed to miner: %v", err)
×
129
        }
×
UNCOV
130
        if _, err := miner.Client.Generate(1); err != nil {
×
131
                t.Fatalf("unable to generate single block: %v", err)
×
132
        }
×
133

UNCOV
134
        return wire.NewOutPoint(txid, 0), output, privKey
×
135
}
136

137
// CreateSpendTx creates a transaction spending the specified output.
138
func CreateSpendTx(t *testing.T, prevOutPoint *wire.OutPoint,
UNCOV
139
        prevOutput *wire.TxOut, privKey *btcec.PrivateKey) *wire.MsgTx {
×
UNCOV
140

×
UNCOV
141
        t.Helper()
×
UNCOV
142

×
UNCOV
143
        // Create a new output.
×
UNCOV
144
        outputAmt := int64(1e8)
×
UNCOV
145
        witnessProgram, _, err := randPubKeyHashScript()
×
UNCOV
146
        require.NoError(t, err, "unable to generate pkScript")
×
UNCOV
147
        output := wire.NewTxOut(outputAmt, witnessProgram)
×
UNCOV
148

×
UNCOV
149
        // Create a new tx.
×
UNCOV
150
        tx := wire.NewMsgTx(2)
×
UNCOV
151
        tx.AddTxIn(wire.NewTxIn(prevOutPoint, nil, nil))
×
UNCOV
152
        tx.AddTxOut(output)
×
UNCOV
153

×
UNCOV
154
        // Generate the witness.
×
UNCOV
155
        sigHashes := input.NewTxSigHashesV0Only(tx)
×
UNCOV
156
        witnessScript, err := txscript.WitnessSignature(
×
UNCOV
157
                tx, sigHashes, 0, prevOutput.Value, prevOutput.PkScript,
×
UNCOV
158
                txscript.SigHashAll, privKey, true,
×
UNCOV
159
        )
×
UNCOV
160
        require.NoError(t, err, "unable to sign tx")
×
UNCOV
161

×
UNCOV
162
        tx.TxIn[0].Witness = witnessScript
×
UNCOV
163

×
UNCOV
164
        return tx
×
UNCOV
165
}
×
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