@@ -2,7 +2,6 @@ package main
22
33import (
44 "fmt"
5- "net"
65 "strconv"
76 "strings"
87 "time"
@@ -16,12 +15,15 @@ import (
1615 "github.com/lightningnetwork/lnd/keychain"
1716 "github.com/lightningnetwork/lnd/lncfg"
1817 "github.com/lightningnetwork/lnd/lnwire"
18+ "github.com/lightningnetwork/lnd/peer"
1919 "github.com/lightningnetwork/lnd/tor"
2020 "github.com/spf13/cobra"
2121)
2222
2323var (
2424 dialTimeout = time .Minute
25+
26+ defaultTorDNSHostPort = "soa.nodes.lightning.directory:53"
2527)
2628
2729type triggerForceCloseCommand struct {
@@ -30,6 +32,8 @@ type triggerForceCloseCommand struct {
3032
3133 APIURL string
3234
35+ TorProxy string
36+
3337 rootKey * rootKey
3438 cmd * cobra.Command
3539}
@@ -63,6 +67,10 @@ does not properly respond to a Data Loss Protection re-establish message).'`,
6367 & cc .APIURL , "apiurl" , defaultAPIURL , "API URL to use (must " +
6468 "be esplora compatible)" ,
6569 )
70+ cc .cmd .Flags ().StringVar (
71+ & cc .TorProxy , "torproxy" , "" , "SOCKS5 proxy to use for Tor " +
72+ "connections (to .onion addresses)" ,
73+ )
6674 cc .rootKey = newRootKey (cc .cmd , "deriving the identity key" )
6775
6876 return cc .cmd
@@ -94,7 +102,9 @@ func (c *triggerForceCloseCommand) Execute(_ *cobra.Command, _ []string) error {
94102 return fmt .Errorf ("error parsing channel point: %w" , err )
95103 }
96104
97- err = requestForceClose (c .Peer , pubKey , outPoint , identityECDH )
105+ err = requestForceClose (
106+ c .Peer , c .TorProxy , pubKey , outPoint , identityECDH ,
107+ )
98108 if err != nil {
99109 return fmt .Errorf ("error requesting force close: %w" , err )
100110 }
@@ -134,34 +144,44 @@ func noiseDial(idKey keychain.SingleKeyECDH, lnAddr *lnwire.NetAddress,
134144 return brontide .Dial (idKey , lnAddr , timeout , netCfg .Dial )
135145}
136146
137- func requestForceClose (peerHost string , peerPubKey * btcec.PublicKey ,
138- channelPoint * wire.OutPoint , identity keychain.SingleKeyECDH ) error {
147+ func connectPeer (peerHost , torProxy string , peerPubKey * btcec.PublicKey ,
148+ identity keychain.SingleKeyECDH ,
149+ dialTimeout time.Duration ) (* peer.Brontide , error ) {
150+
151+ var dialNet tor.Net = & tor.ClearNet {}
152+ if torProxy != "" {
153+ dialNet = & tor.ProxyNet {
154+ SOCKS : torProxy ,
155+ DNS : defaultTorDNSHostPort ,
156+ StreamIsolation : false ,
157+ SkipProxyForClearNetTargets : true ,
158+ }
159+ }
139160
161+ log .Debugf ("Attempting to resolve peer address %v" , peerHost )
140162 peerAddr , err := lncfg .ParseLNAddressString (
141- peerHost , "9735" , net .ResolveTCPAddr ,
163+ peerHost , "9735" , dialNet .ResolveTCPAddr ,
142164 )
143165 if err != nil {
144- return fmt .Errorf ("error parsing peer address: %w" , err )
166+ return nil , fmt .Errorf ("error parsing peer address: %w" , err )
145167 }
146168
147- channelID := lnwire .NewChanIDFromOutPoint (channelPoint )
148-
149- conn , err := noiseDial (
150- identity , peerAddr , & tor.ClearNet {}, dialTimeout ,
151- )
169+ log .Debugf ("Attempting to dial resolved peer address %v" ,
170+ peerAddr .String ())
171+ conn , err := noiseDial (identity , peerAddr , dialNet , dialTimeout )
152172 if err != nil {
153- return fmt .Errorf ("error dialing peer: %w" , err )
173+ return nil , fmt .Errorf ("error dialing peer: %w" , err )
154174 }
155175
156- log .Infof ("Attempting to connect to peer %x, dial timeout is %v" ,
157- peerPubKey .SerializeCompressed (), dialTimeout )
176+ log .Infof ("Attempting to establish p2p connection to peer %x, dial" +
177+ "timeout is %v" , peerPubKey .SerializeCompressed (), dialTimeout )
158178 req := & connmgr.ConnReq {
159179 Addr : peerAddr ,
160180 Permanent : false ,
161181 }
162182 p , err := lnd .ConnectPeer (conn , req , chainParams , identity )
163183 if err != nil {
164- return fmt .Errorf ("error connecting to peer: %w" , err )
184+ return nil , fmt .Errorf ("error connecting to peer: %w" , err )
165185 }
166186
167187 log .Infof ("Connection established to peer %x" ,
@@ -171,10 +191,25 @@ func requestForceClose(peerHost string, peerPubKey *btcec.PublicKey,
171191 select {
172192 case <- p .ActiveSignal ():
173193 case <- p .QuitSignal ():
174- return fmt .Errorf ("peer %x disconnected" ,
194+ return nil , fmt .Errorf ("peer %x disconnected" ,
175195 peerPubKey .SerializeCompressed ())
176196 }
177197
198+ return p , nil
199+ }
200+
201+ func requestForceClose (peerHost , torProxy string , peerPubKey * btcec.PublicKey ,
202+ channelPoint * wire.OutPoint , identity keychain.SingleKeyECDH ) error {
203+
204+ p , err := connectPeer (
205+ peerHost , torProxy , peerPubKey , identity , dialTimeout ,
206+ )
207+ if err != nil {
208+ return fmt .Errorf ("error connecting to peer: %w" , err )
209+ }
210+
211+ channelID := lnwire .NewChanIDFromOutPoint (channelPoint )
212+
178213 // Channel ID (32 byte) + u16 for the data length (which will be 0).
179214 data := make ([]byte , 34 )
180215 copy (data [:32 ], channelID [:])
0 commit comments