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

lightningnetwork / lnd / 12583319996

02 Jan 2025 01:38PM UTC coverage: 57.522% (-1.1%) from 58.598%
12583319996

Pull #9361

github

starius
fn/ContextGuard: use context.AfterFunc to wait

Simplifies context cancellation handling by using context.AfterFunc instead of a
goroutine to wait for context cancellation. This approach avoids the overhead of
a goroutine during the waiting period.

For ctxQuitUnsafe, since g.quit is closed only in the Quit method (which also
cancels all associated contexts), waiting on context cancellation ensures the
same behavior without unnecessary dependency on g.quit.

Added a test to ensure that the Create method does not launch any goroutines.
Pull Request #9361: fn: optimize context guard

102587 of 178344 relevant lines covered (57.52%)

24734.33 hits per line

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

72.83
/input/taproot.go
1
package input
2

3
import (
4
        "fmt"
5

6
        "github.com/btcsuite/btcd/btcec/v2"
7
        "github.com/btcsuite/btcd/btcec/v2/schnorr"
8
        "github.com/btcsuite/btcd/txscript"
9
        "github.com/btcsuite/btcd/wire"
10
        "github.com/btcsuite/btcwallet/waddrmgr"
11
        "github.com/lightningnetwork/lnd/fn/v2"
12
)
13

14
const (
15
        // PubKeyFormatCompressedOdd is the identifier prefix byte for a public
16
        // key whose Y coordinate is odd when serialized in the compressed
17
        // format per section 2.3.4 of
18
        // [SEC1](https://secg.org/sec1-v2.pdf#subsubsection.2.3.4).
19
        // This is copied from the github.com/decred/dcrd/dcrec/secp256k1/v4 to
20
        // avoid needing to directly reference (and by accident pull in
21
        // incompatible crypto primitives) the package.
22
        PubKeyFormatCompressedOdd byte = 0x03
23
)
24

25
// AuxTapLeaf is a type alias for an optional tapscript leaf that may be added
26
// to the tapscript tree of HTLC and commitment outputs.
27
type AuxTapLeaf = fn.Option[txscript.TapLeaf]
28

29
// NoneTapLeaf returns an empty optional tapscript leaf.
30
func NoneTapLeaf() AuxTapLeaf {
19✔
31
        return fn.None[txscript.TapLeaf]()
19✔
32
}
19✔
33

34
// HtlcIndex represents the monotonically increasing counter that is used to
35
// identify HTLCs created by a peer.
36
type HtlcIndex = uint64
37

38
// HtlcAuxLeaf is a type that represents an auxiliary leaf for an HTLC output.
39
// An HTLC may have up to two aux leaves: one for the output on the commitment
40
// transaction, and one for the second level HTLC.
41
type HtlcAuxLeaf struct {
42
        AuxTapLeaf
43

44
        // SecondLevelLeaf is the auxiliary leaf for the second level HTLC
45
        // success or timeout transaction.
46
        SecondLevelLeaf AuxTapLeaf
47
}
48

49
// HtlcAuxLeaves is a type alias for a map of optional tapscript leaves.
50
type HtlcAuxLeaves = map[HtlcIndex]HtlcAuxLeaf
51

52
// NewTxSigHashesV0Only returns a new txscript.TxSigHashes instance that will
53
// only calculate the sighash midstate values for segwit v0 inputs and can
54
// therefore never be used for transactions that want to spend segwit v1
55
// (taproot) inputs.
56
func NewTxSigHashesV0Only(tx *wire.MsgTx) *txscript.TxSigHashes {
6,319✔
57
        // The canned output fetcher returns a wire.TxOut instance with the
6,319✔
58
        // given pk script and amount. We can get away with nil since the first
6,319✔
59
        // thing the TxSigHashes constructor checks is the length of the pk
6,319✔
60
        // script and whether it matches taproot output script length. If the
6,319✔
61
        // length doesn't match it assumes v0 inputs only.
6,319✔
62
        nilFetcher := txscript.NewCannedPrevOutputFetcher(nil, 0)
6,319✔
63
        return txscript.NewTxSigHashes(tx, nilFetcher)
6,319✔
64
}
6,319✔
65

66
// MultiPrevOutFetcher returns a txscript.MultiPrevOutFetcher for the given set
67
// of inputs.
68
func MultiPrevOutFetcher(inputs []Input) (*txscript.MultiPrevOutFetcher, error) {
61✔
69
        fetcher := txscript.NewMultiPrevOutFetcher(nil)
61✔
70
        for _, inp := range inputs {
154✔
71
                op := inp.OutPoint()
93✔
72
                desc := inp.SignDesc()
93✔
73

93✔
74
                if op == EmptyOutPoint {
93✔
75
                        return nil, fmt.Errorf("missing input outpoint")
×
76
                }
×
77

78
                if desc == nil || desc.Output == nil {
93✔
79
                        return nil, fmt.Errorf("missing input utxo information")
×
80
                }
×
81

82
                fetcher.AddPrevOut(op, desc.Output)
93✔
83
        }
84

85
        return fetcher, nil
61✔
86
}
87

88
// TapscriptFullTree creates a waddrmgr.Tapscript for the given internal key and
89
// tree leaves.
90
func TapscriptFullTree(internalKey *btcec.PublicKey,
91
        allTreeLeaves ...txscript.TapLeaf) *waddrmgr.Tapscript {
1✔
92

1✔
93
        tree := txscript.AssembleTaprootScriptTree(allTreeLeaves...)
1✔
94
        rootHash := tree.RootNode.TapHash()
1✔
95
        tapKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash[:])
1✔
96

1✔
97
        var outputKeyYIsOdd bool
1✔
98
        if tapKey.SerializeCompressed()[0] == PubKeyFormatCompressedOdd {
2✔
99
                outputKeyYIsOdd = true
1✔
100
        }
1✔
101

102
        return &waddrmgr.Tapscript{
1✔
103
                Type: waddrmgr.TapscriptTypeFullTree,
1✔
104
                ControlBlock: &txscript.ControlBlock{
1✔
105
                        InternalKey:     internalKey,
1✔
106
                        OutputKeyYIsOdd: outputKeyYIsOdd,
1✔
107
                        LeafVersion:     txscript.BaseLeafVersion,
1✔
108
                },
1✔
109
                Leaves: allTreeLeaves,
1✔
110
        }
1✔
111
}
112

113
// TapscriptPartialReveal creates a waddrmgr.Tapscript for the given internal
114
// key and revealed script.
115
func TapscriptPartialReveal(internalKey *btcec.PublicKey,
116
        revealedLeaf txscript.TapLeaf,
117
        inclusionProof []byte) *waddrmgr.Tapscript {
1✔
118

1✔
119
        controlBlock := &txscript.ControlBlock{
1✔
120
                InternalKey:    internalKey,
1✔
121
                LeafVersion:    txscript.BaseLeafVersion,
1✔
122
                InclusionProof: inclusionProof,
1✔
123
        }
1✔
124
        rootHash := controlBlock.RootHash(revealedLeaf.Script)
1✔
125
        tapKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash)
1✔
126

1✔
127
        if tapKey.SerializeCompressed()[0] == PubKeyFormatCompressedOdd {
2✔
128
                controlBlock.OutputKeyYIsOdd = true
1✔
129
        }
1✔
130

131
        return &waddrmgr.Tapscript{
1✔
132
                Type:           waddrmgr.TapscriptTypePartialReveal,
1✔
133
                ControlBlock:   controlBlock,
1✔
134
                RevealedScript: revealedLeaf.Script,
1✔
135
        }
1✔
136
}
137

138
// TapscriptRootHashOnly creates a waddrmgr.Tapscript for the given internal key
139
// and root hash.
140
func TapscriptRootHashOnly(internalKey *btcec.PublicKey,
141
        rootHash []byte) *waddrmgr.Tapscript {
×
142

×
143
        controlBlock := &txscript.ControlBlock{
×
144
                InternalKey: internalKey,
×
145
        }
×
146

×
147
        tapKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash)
×
148
        if tapKey.SerializeCompressed()[0] == PubKeyFormatCompressedOdd {
×
149
                controlBlock.OutputKeyYIsOdd = true
×
150
        }
×
151

152
        return &waddrmgr.Tapscript{
×
153
                Type:         waddrmgr.TaprootKeySpendRootHash,
×
154
                ControlBlock: controlBlock,
×
155
                RootHash:     rootHash,
×
156
        }
×
157
}
158

159
// TapscriptFullKeyOnly creates a waddrmgr.Tapscript for the given full Taproot
160
// key.
161
func TapscriptFullKeyOnly(taprootKey *btcec.PublicKey) *waddrmgr.Tapscript {
×
162
        return &waddrmgr.Tapscript{
×
163
                Type:          waddrmgr.TaprootFullKeyOnly,
×
164
                FullOutputKey: taprootKey,
×
165
        }
×
166
}
×
167

168
// PayToTaprootScript creates a new script to pay to a version 1 (taproot)
169
// witness program. The passed public key will be serialized as an x-only key
170
// to create the witness program.
171
func PayToTaprootScript(taprootKey *btcec.PublicKey) ([]byte, error) {
2,846✔
172
        builder := txscript.NewScriptBuilder()
2,846✔
173

2,846✔
174
        builder.AddOp(txscript.OP_1)
2,846✔
175
        builder.AddData(schnorr.SerializePubKey(taprootKey))
2,846✔
176

2,846✔
177
        return builder.Script()
2,846✔
178
}
2,846✔
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