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

lightningnetwork / lnd / 13523316608

25 Feb 2025 02:12PM UTC coverage: 49.351% (-9.5%) from 58.835%
13523316608

Pull #9549

github

yyforyongyu
routing/chainview: refactor `TestFilteredChainView`

So each test has its own miner and chainView.
Pull Request #9549: Fix unit test flake `TestHistoricalConfDetailsTxIndex`

0 of 120 new or added lines in 1 file covered. (0.0%)

27196 existing lines in 434 files now uncovered.

100945 of 204543 relevant lines covered (49.35%)

1.54 hits per line

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

90.65
/lnwallet/transactions.go
1
package lnwallet
2

3
import (
4
        "encoding/binary"
5
        "fmt"
6

7
        "github.com/btcsuite/btcd/btcec/v2"
8
        "github.com/btcsuite/btcd/btcutil"
9
        "github.com/btcsuite/btcd/wire"
10
        "github.com/lightningnetwork/lnd/channeldb"
11
        "github.com/lightningnetwork/lnd/input"
12
)
13

14
const (
15
        // StateHintSize is the total number of bytes used between the sequence
16
        // number and locktime of the commitment transaction use to encode a hint
17
        // to the state number of a particular commitment transaction.
18
        StateHintSize = 6
19

20
        // MaxStateHint is the maximum state number we're able to encode using
21
        // StateHintSize bytes amongst the sequence number and locktime fields
22
        // of the commitment transaction.
23
        maxStateHint uint64 = (1 << 48) - 1
24
)
25

26
var (
27
        // TimelockShift is used to make sure the commitment transaction is
28
        // spendable by setting the locktime with it so that it is larger than
29
        // 500,000,000, thus interpreting it as Unix epoch timestamp and not
30
        // a block height. It is also smaller than the current timestamp which
31
        // has bit (1 << 30) set, so there is no risk of having the commitment
32
        // transaction be rejected. This way we can safely use the lower 24 bits
33
        // of the locktime field for part of the obscured commitment transaction
34
        // number.
35
        TimelockShift = uint32(1 << 29)
36
)
37

38
// CreateHtlcSuccessTx creates a transaction that spends the output on the
39
// commitment transaction of the peer that receives an HTLC. This transaction
40
// essentially acts as an off-chain covenant as it's only permitted to spend
41
// the designated HTLC output, and also that spend can _only_ be used as a
42
// state transition to create another output which actually allows redemption
43
// or revocation of an HTLC.
44
//
45
// In order to spend the segwit v0 HTLC output, the witness for the passed
46
// transaction should be:
47
//   - <0> <sender sig> <recvr sig> <preimage>
48
//
49
// In order to spend the segwit v1 (taproot) HTLC output, the witness for the
50
// passed transaction should be:
51
//   - <sender sig> <receiver sig> <preimage> <success_script> <control_block>
52
func CreateHtlcSuccessTx(chanType channeldb.ChannelType, initiator bool,
53
        htlcOutput wire.OutPoint, htlcAmt btcutil.Amount, csvDelay,
54
        leaseExpiry uint32, revocationKey, delayKey *btcec.PublicKey,
55
        auxLeaf input.AuxTapLeaf) (*wire.MsgTx, error) {
3✔
56

3✔
57
        // Create a version two transaction (as the success version of this
3✔
58
        // spends an output with a CSV timeout).
3✔
59
        successTx := wire.NewMsgTx(2)
3✔
60

3✔
61
        // The input to the transaction is the outpoint that creates the
3✔
62
        // original HTLC on the sender's commitment transaction. Set the
3✔
63
        // sequence number based on the channel type.
3✔
64
        txin := &wire.TxIn{
3✔
65
                PreviousOutPoint: htlcOutput,
3✔
66
                Sequence:         HtlcSecondLevelInputSequence(chanType),
3✔
67
        }
3✔
68
        successTx.AddTxIn(txin)
3✔
69

3✔
70
        // Next, we'll generate the script used as the output for all second
3✔
71
        // level HTLC which forces a covenant w.r.t what can be done with all
3✔
72
        // HTLC outputs.
3✔
73
        scriptInfo, err := SecondLevelHtlcScript(
3✔
74
                chanType, initiator, revocationKey, delayKey, csvDelay,
3✔
75
                leaseExpiry, auxLeaf,
3✔
76
        )
3✔
77
        if err != nil {
3✔
78
                return nil, err
×
79
        }
×
80

81
        // Finally, the output is simply the amount of the HTLC (minus the
82
        // required fees), paying to the timeout script.
83
        successTx.AddTxOut(&wire.TxOut{
3✔
84
                Value:    int64(htlcAmt),
3✔
85
                PkScript: scriptInfo.PkScript(),
3✔
86
        })
3✔
87

3✔
88
        return successTx, nil
3✔
89
}
90

91
// CreateHtlcTimeoutTx creates a transaction that spends the HTLC output on the
92
// commitment transaction of the peer that created an HTLC (the sender). This
93
// transaction essentially acts as an off-chain covenant as it spends a 2-of-2
94
// multi-sig output. This output requires a signature from both the sender and
95
// receiver of the HTLC. By using a distinct transaction, we're able to
96
// uncouple the timeout and delay clauses of the HTLC contract. This
97
// transaction is locked with an absolute lock-time so the sender can only
98
// attempt to claim the output using it after the lock time has passed.
99
//
100
// In order to spend the HTLC output for segwit v0, the witness for the passed
101
// transaction should be:
102
//   - <0> <sender sig> <receiver sig> <0>
103
//
104
// In order to spend the HTLC output for segwit v1, then witness for the passed
105
// transaction should be:
106
//   - <sender sig> <receiver sig> <timeout_script> <control_block>
107
//
108
// NOTE: The passed amount for the HTLC should take into account the required
109
// fee rate at the time the HTLC was created. The fee should be able to
110
// entirely pay for this (tiny: 1-in 1-out) transaction.
111
func CreateHtlcTimeoutTx(chanType channeldb.ChannelType, initiator bool,
112
        htlcOutput wire.OutPoint, htlcAmt btcutil.Amount,
113
        cltvExpiry, csvDelay, leaseExpiry uint32,
114
        revocationKey, delayKey *btcec.PublicKey,
115
        auxLeaf input.AuxTapLeaf) (*wire.MsgTx, error) {
3✔
116

3✔
117
        // Create a version two transaction (as the success version of this
3✔
118
        // spends an output with a CSV timeout), and set the lock-time to the
3✔
119
        // specified absolute lock-time in blocks.
3✔
120
        timeoutTx := wire.NewMsgTx(2)
3✔
121
        timeoutTx.LockTime = cltvExpiry
3✔
122

3✔
123
        // The input to the transaction is the outpoint that creates the
3✔
124
        // original HTLC on the sender's commitment transaction. Set the
3✔
125
        // sequence number based on the channel type.
3✔
126
        txin := &wire.TxIn{
3✔
127
                PreviousOutPoint: htlcOutput,
3✔
128
                SignatureScript:  []byte{},
3✔
129
                Witness:          [][]byte{},
3✔
130
                Sequence:         HtlcSecondLevelInputSequence(chanType),
3✔
131
        }
3✔
132
        timeoutTx.AddTxIn(txin)
3✔
133

3✔
134
        // Next, we'll generate the script used as the output for all second
3✔
135
        // level HTLC which forces a covenant w.r.t what can be done with all
3✔
136
        // HTLC outputs.
3✔
137
        scriptInfo, err := SecondLevelHtlcScript(
3✔
138
                chanType, initiator, revocationKey, delayKey, csvDelay,
3✔
139
                leaseExpiry, auxLeaf,
3✔
140
        )
3✔
141
        if err != nil {
3✔
142
                return nil, err
×
143
        }
×
144

145
        // Finally, the output is simply the amount of the HTLC (minus the
146
        // required fees), paying to the regular second level HTLC script.
147
        timeoutTx.AddTxOut(&wire.TxOut{
3✔
148
                Value:    int64(htlcAmt),
3✔
149
                PkScript: scriptInfo.PkScript(),
3✔
150
        })
3✔
151

3✔
152
        return timeoutTx, nil
3✔
153
}
154

155
// SetStateNumHint encodes the current state number within the passed
156
// commitment transaction by re-purposing the locktime and sequence fields in
157
// the commitment transaction to encode the obfuscated state number.  The state
158
// number is encoded using 48 bits. The lower 24 bits of the lock time are the
159
// lower 24 bits of the obfuscated state number and the lower 24 bits of the
160
// sequence field are the higher 24 bits. Finally before encoding, the
161
// obfuscator is XOR'd against the state number in order to hide the exact
162
// state number from the PoV of outside parties.
163
func SetStateNumHint(commitTx *wire.MsgTx, stateNum uint64,
164
        obfuscator [StateHintSize]byte) error {
3✔
165

3✔
166
        // With the current schema we are only able to encode state num
3✔
167
        // hints up to 2^48. Therefore if the passed height is greater than our
3✔
168
        // state hint ceiling, then exit early.
3✔
169
        if stateNum > maxStateHint {
3✔
UNCOV
170
                return fmt.Errorf("unable to encode state, %v is greater "+
×
UNCOV
171
                        "state num that max of %v", stateNum, maxStateHint)
×
UNCOV
172
        }
×
173

174
        if len(commitTx.TxIn) != 1 {
3✔
UNCOV
175
                return fmt.Errorf("commitment tx must have exactly 1 input, "+
×
UNCOV
176
                        "instead has %v", len(commitTx.TxIn))
×
UNCOV
177
        }
×
178

179
        // Convert the obfuscator into a uint64, then XOR that against the
180
        // targeted height in order to obfuscate the state number of the
181
        // commitment transaction in the case that either commitment
182
        // transaction is broadcast directly on chain.
183
        var obfs [8]byte
3✔
184
        copy(obfs[2:], obfuscator[:])
3✔
185
        xorInt := binary.BigEndian.Uint64(obfs[:])
3✔
186

3✔
187
        stateNum = stateNum ^ xorInt
3✔
188

3✔
189
        // Set the height bit of the sequence number in order to disable any
3✔
190
        // sequence locks semantics.
3✔
191
        commitTx.TxIn[0].Sequence = uint32(stateNum>>24) | wire.SequenceLockTimeDisabled
3✔
192
        commitTx.LockTime = uint32(stateNum&0xFFFFFF) | TimelockShift
3✔
193

3✔
194
        return nil
3✔
195
}
196

197
// GetStateNumHint recovers the current state number given a commitment
198
// transaction which has previously had the state number encoded within it via
199
// setStateNumHint and a shared obfuscator.
200
//
201
// See setStateNumHint for further details w.r.t exactly how the state-hints
202
// are encoded.
203
func GetStateNumHint(commitTx *wire.MsgTx, obfuscator [StateHintSize]byte) uint64 {
3✔
204
        // Convert the obfuscator into a uint64, this will be used to
3✔
205
        // de-obfuscate the final recovered state number.
3✔
206
        var obfs [8]byte
3✔
207
        copy(obfs[2:], obfuscator[:])
3✔
208
        xorInt := binary.BigEndian.Uint64(obfs[:])
3✔
209

3✔
210
        // Retrieve the state hint from the sequence number and locktime
3✔
211
        // of the transaction.
3✔
212
        stateNumXor := uint64(commitTx.TxIn[0].Sequence&0xFFFFFF) << 24
3✔
213
        stateNumXor |= uint64(commitTx.LockTime & 0xFFFFFF)
3✔
214

3✔
215
        // Finally, to obtain the final state number, we XOR by the obfuscator
3✔
216
        // value to de-obfuscate the state number.
3✔
217
        return stateNumXor ^ xorInt
3✔
218
}
3✔
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