@@ -103,63 +103,146 @@ func (cfg *LitNodeConfig) GenerateListeningPorts() {
103103 }
104104}
105105
106+ // litArgs holds a key-value map of config option to config value. An empty
107+ // string value means that the config option is a boolean.
108+ type litArgs struct {
109+ args map [string ]string
110+
111+ mu sync.Mutex
112+ }
113+
114+ // deleteArg deletes the argument with the given name from the set if it is
115+ // present.
116+ func (l * litArgs ) deleteArg (argName string ) {
117+ l .mu .Lock ()
118+ defer l .mu .Unlock ()
119+
120+ delete (l .args , argName )
121+ }
122+
123+ // addArg adds a new argument to the set. An empty value string will mean that
124+ // the key will be added as a boolean flag.
125+ func (l * litArgs ) addArg (name , value string ) {
126+ l .mu .Lock ()
127+ defer l .mu .Unlock ()
128+
129+ l .args [name ] = value
130+ }
131+
132+ // toArgList converts the litArgs map to an arguments string slice.
133+ func (l * litArgs ) toArgList () []string {
134+ l .mu .Lock ()
135+ defer l .mu .Unlock ()
136+
137+ args := make ([]string , 0 , len (l .args ))
138+ for arg , setting := range l .args {
139+ if setting == "" {
140+ args = append (args , fmt .Sprintf ("--%s" , arg ))
141+ continue
142+ }
143+
144+ args = append (args , fmt .Sprintf ("--%s=%s" , arg , setting ))
145+ }
146+
147+ return args
148+ }
149+
150+ // LitArgOption defines the signature of a functional option that can be used
151+ // to tweak the default arguments of a Litd node.
152+ type LitArgOption func (args * litArgs )
153+
154+ // WithoutLitArg can be used to delete a litd config option.
155+ func WithoutLitArg (arg string ) LitArgOption {
156+ return func (args * litArgs ) {
157+ args .deleteArg (arg )
158+ }
159+ }
160+
161+ // WithLitArg can be used to set a Litd config option. An empty value string
162+ // will mean that the key will be added as a boolean flag.
163+ func WithLitArg (key , value string ) LitArgOption {
164+ return func (args * litArgs ) {
165+ args .addArg (key , value )
166+ }
167+ }
168+
106169// GenArgs generates a slice of command line arguments from the lightning node
107170// config struct.
108- func (cfg * LitNodeConfig ) GenArgs () []string {
171+ func (cfg * LitNodeConfig ) GenArgs (opts ... LitArgOption ) []string {
172+ args := cfg .defaultLitdArgs ()
173+
174+ for _ , opt := range opts {
175+ opt (args )
176+ }
177+
178+ return args .toArgList ()
179+ }
180+
181+ // defaultLitArgs generates the default arguments to be used with a Litd node.
182+ func (cfg * LitNodeConfig ) defaultLitdArgs () * litArgs {
109183 var (
110- litArgs = [ ]string {
111- fmt . Sprintf ( "-- httpslisten=%s" , cfg .LitAddr () ),
112- fmt . Sprintf ( "-- insecure-httplisten=%s" , cfg .LitRESTAddr () ),
113- fmt . Sprintf ( "-- lit-dir=%s" , cfg .LitDir ) ,
114- fmt . Sprintf ( "-- faraday.faradaydir=%s" , cfg .FaradayDir ) ,
115- fmt . Sprintf ( "-- loop.loopdir=%s" , cfg .LoopDir ) ,
116- fmt . Sprintf ( "-- pool.basedir=%s" , cfg .PoolDir ) ,
117- fmt . Sprintf ( "-- uipassword=%s" , cfg .UIPassword ) ,
118- "-- enablerest" ,
119- "-- restcors= *" ,
184+ args = map [ string ]string {
185+ " httpslisten" : cfg .LitAddr (),
186+ " insecure-httplisten" : cfg .LitRESTAddr (),
187+ " lit-dir" : cfg .LitDir ,
188+ " faraday.faradaydir" : cfg .FaradayDir ,
189+ " loop.loopdir" : cfg .LoopDir ,
190+ " pool.basedir" : cfg .PoolDir ,
191+ " uipassword" : cfg .UIPassword ,
192+ "enablerest" : " " ,
193+ "restcors" : " *" ,
120194 }
121195 )
122- litArgs = append (litArgs , cfg .LitArgs ... )
196+ for _ , arg := range cfg .LitArgs {
197+ parts := strings .Split (arg , "=" )
198+ option := strings .TrimLeft (parts [0 ], "--" )
199+ switch len (parts ) {
200+ case 1 :
201+ args [option ] = ""
202+ case 2 :
203+ args [option ] = parts [1 ]
204+ }
205+ }
123206
124207 switch cfg .NetParams {
125208 case & chaincfg .TestNet3Params :
126- litArgs = append ( litArgs , "--network= testnet")
209+ args [ "network" ] = " testnet"
127210 case & chaincfg .SimNetParams :
128- litArgs = append ( litArgs , "--network= simnet")
211+ args [ "network" ] = " simnet"
129212 case & chaincfg .RegressionNetParams :
130- litArgs = append ( litArgs , "--network= regtest")
213+ args [ "network" ] = " regtest"
131214 }
132215
133216 // In remote mode, we don't need any lnd specific arguments other than
134217 // those we need to connect.
135218 if cfg .RemoteMode {
136- litArgs = append (litArgs , "--lnd-mode=remote" )
137- litArgs = append (litArgs , fmt .Sprintf (
138- "--remote.lnd.rpcserver=%s" , cfg .RPCAddr ()),
139- )
140- litArgs = append (litArgs , fmt .Sprintf (
141- "--remote.lnd.tlscertpath=%s" , cfg .TLSCertPath ),
142- )
143- litArgs = append (litArgs , fmt .Sprintf (
144- "--remote.lnd.macaroonpath=%s" , cfg .AdminMacPath ),
145- )
219+ args ["lnd-mode" ] = "remote"
220+ args ["remote.lnd.rpcserver" ] = cfg .RPCAddr ()
221+ args ["remote.lnd.tlscertpath" ] = cfg .TLSCertPath
222+ args ["remote.lnd.macaroonpath" ] = cfg .AdminMacPath
146223
147- return litArgs
224+ return & litArgs { args : args }
148225 }
149226
150227 // All arguments so far were for lnd. Let's namespace them now so we can
151228 // add args for the other daemons and LiT itself afterwards.
152- litArgs = append ( litArgs , cfg . LitArgs ... )
153- litArgs = append ( litArgs , "--lnd-mode=integrated" )
229+ args [ "lnd-mode" ] = "integrated"
230+
154231 lndArgs := cfg .BaseNodeConfig .GenArgs ()
155232 for idx := range lndArgs {
156- litArgs = append (
157- litArgs ,
158- strings .ReplaceAll (lndArgs [idx ], "--" , "--lnd." ),
159- )
233+ arg := strings .ReplaceAll (lndArgs [idx ], "--" , "--lnd." )
234+
235+ parts := strings .Split (arg , "=" )
236+ option := strings .TrimLeft (parts [0 ], "--" )
237+ switch len (parts ) {
238+ case 1 :
239+ args [option ] = ""
240+ case 2 :
241+ args [option ] = parts [1 ]
242+ }
160243 }
161244
162- return litArgs
245+ return & litArgs { args : args }
163246}
164247
165248// policyUpdateMap defines a type to store channel policy updates. It has the
@@ -456,11 +539,11 @@ func renameFile(fromFileName, toFileName string) {
456539// This may not clean up properly if an error is returned, so the caller should
457540// call shutdown() regardless of the return value.
458541func (hn * HarnessNode ) start (litdBinary string , litdError chan <- error ,
459- wait bool ) error {
542+ wait bool , litArgOpts ... LitArgOption ) error {
460543
461544 hn .quit = make (chan struct {})
462545
463- args := hn .Cfg .GenArgs ()
546+ args := hn .Cfg .GenArgs (litArgOpts ... )
464547 hn .cmd = exec .Command (litdBinary , args ... )
465548
466549 // Redirect stderr output to buffer
0 commit comments