github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/lit.go (about) 1 package main 2 3 import ( 4 "os" 5 "os/signal" 6 "runtime" 7 "syscall" 8 "time" 9 10 "github.com/mit-dci/lit/logging" 11 12 "github.com/mit-dci/lit/coinparam" 13 consts "github.com/mit-dci/lit/consts" 14 "github.com/mit-dci/lit/litrpc" 15 "github.com/mit-dci/lit/lnutil" 16 "github.com/mit-dci/lit/qln" 17 18 flags "github.com/jessevdk/go-flags" 19 ) 20 21 type litConfig struct { // define a struct for usage with go-flags 22 // networks lit can try connecting to 23 Tn3host string `long:"tn3" description:"Connect to bitcoin testnet3."` 24 Bc2host string `long:"bc2" description:"bc2 full node."` 25 Lt4host string `long:"lt4" description:"Connect to litecoin testnet4."` 26 Reghost string `long:"reg" description:"Connect to bitcoin regtest."` 27 Litereghost string `long:"litereg" description:"Connect to litecoin regtest."` 28 Dummyusdhost string `long:"dusd" description:"Connect to Dummy USD node."` 29 Rtvtchost string `long:"rtvtc" description:"Connect to Vertcoin regtest node."` 30 Tvtchost string `long:"tvtc" description:"Connect to Vertcoin test node."` 31 Vtchost string `long:"vtc" description:"Connect to Vertcoin."` 32 // system specific configs 33 LitHomeDir string `long:"dir" description:"Specify Home Directory of lit as an absolute path."` 34 TrackerURL string `long:"tracker" description:"LN address tracker URL http|https://host:port"` 35 ConfigFile string 36 UnauthRPC bool `long:"unauthrpc" description:"Enables unauthenticated Websocket RPC"` 37 38 // proxy 39 ProxyURL string `long:"proxy" description:"SOCKS5 proxy to use for communicating with the network"` 40 LitProxyURL string `long:"litproxy" description:"SOCKS5 proxy to use for Lit's network communications. Overridden by the proxy flag."` 41 ChainProxyURL string `long:"chainproxy" description:"SOCKS5 proxy to use for Wallit's network communications. Overridden by the proxy flag."` 42 43 // UPnP port forwarding and NAT Traversal 44 Nat string `long:"nat" description:"Toggle upnp or pmp NAT Traversal NAT Punching"` 45 //resync and tower config 46 Resync string `long:"resync" description:"Resync the given chain from the given tip (requires --tip) or from default params"` 47 Tip int32 `long:"tip" description:"Given tip to resync from"` 48 Tower bool `long:"tower" description:"Watchtower: Run a watching node"` 49 Hard bool `short:"t" long:"hard" description:"Flag to set networks."` 50 51 // logging and debug parameters 52 LogLevel []bool `short:"v" description:"Set verbosity level to verbose (-v), very verbose (-vv) or very very verbose (-vvv)"` 53 54 // rpc server config 55 Rpcport uint16 `short:"p" long:"rpcport" description:"Set RPC port to connect to"` 56 Rpchost string `long:"rpchost" description:"Set RPC host to listen to"` 57 // auto config 58 AutoReconnect bool `long:"autoReconnect" description:"Attempts to automatically reconnect to known peers periodically."` 59 AutoReconnectInterval int64 `long:"autoReconnectInterval" description:"The interval (in seconds) the reconnect logic should be executed"` 60 AutoReconnectOnlyConnectedCoins bool `long:"autoReconnectOnlyConnectedCoins" description:"Only reconnect to peers that we have channels with in a coin whose coin daemon is available"` 61 AutoListenPort int `long:"autoListenPort" description:"When auto reconnect enabled, starts listening on this port"` 62 NoAutoListen bool `long:"noautolisten" description:"Don't automatically listen on any ports."` 63 Params *coinparam.Params 64 } 65 66 var ( 67 defaultLitHomeDirName = os.Getenv("HOME") + "/.lit" 68 defaultTrackerURL = "http://hubris.media.mit.edu:46580" 69 defaultKeyFileName = "privkey.hex" 70 defaultConfigFilename = "lit.conf" 71 defaultHomeDir = os.Getenv("HOME") 72 defaultRpcport = uint16(8001) 73 defaultRpchost = "localhost" 74 defaultAutoReconnect = true 75 defaultNoAutoListen = false 76 defaultAutoListenPort = 2448 77 defaultAutoReconnectInterval = int64(60) 78 defaultUpnPFlag = false 79 defaultLogLevel = 0 80 defaultAutoReconnectOnlyConnectedCoins = false 81 defaultUnauthRPC = false 82 ) 83 84 func fileExists(name string) bool { 85 if _, err := os.Stat(name); err != nil { 86 if os.IsNotExist(err) { 87 return false 88 } 89 } 90 return true 91 } 92 93 // newConfigParser returns a new command line flags parser. 94 func newConfigParser(conf *litConfig, options flags.Options) *flags.Parser { 95 parser := flags.NewParser(conf, options) 96 return parser 97 } 98 func linkWallets(node *qln.LitNode, key *[32]byte, conf *litConfig) error { 99 // for now, wallets are linked to the litnode on startup, and 100 // can't appear / disappear while it's running. Later 101 // could support dynamically adding / removing wallets 102 103 // order matters; the first registered wallet becomes the default 104 105 var err error 106 // try regtest 107 if !lnutil.NopeString(conf.Reghost) { 108 p := &coinparam.RegressionNetParams 109 logging.Infof("reg: %s\n", conf.Reghost) 110 resync := false 111 conf.Tip = consts.BitcoinRegtestBHeight 112 if conf.Resync == "reg" { 113 if conf.Tip < consts.BitcoinRegtestBHeight { 114 conf.Tip = consts.BitcoinRegtestBHeight 115 } 116 resync = true 117 } 118 err = node.LinkBaseWallet(key, conf.Tip, resync, 119 conf.Tower, conf.Reghost, conf.ChainProxyURL, p) 120 if err != nil { 121 return err 122 } 123 } 124 // try testnet3 125 if !lnutil.NopeString(conf.Tn3host) { 126 p := &coinparam.TestNet3Params 127 resync := false 128 conf.Tip = consts.BitcoinTestnet3BHeight 129 if conf.Resync == "tn3" { 130 if conf.Tip < consts.BitcoinTestnet3BHeight { 131 conf.Tip = consts.BitcoinTestnet3BHeight 132 } 133 resync = true 134 } 135 err = node.LinkBaseWallet( 136 key, conf.Tip, resync, conf.Tower, 137 conf.Tn3host, conf.ChainProxyURL, p) 138 if err != nil { 139 return err 140 } 141 } 142 // try litecoin regtest 143 if !lnutil.NopeString(conf.Litereghost) { 144 p := &coinparam.LiteRegNetParams 145 resync := false 146 conf.Tip = consts.BitcoinRegtestBHeight 147 if conf.Resync == "ltcreg" { 148 if conf.Tip < consts.BitcoinRegtestBHeight { 149 conf.Tip = consts.BitcoinRegtestBHeight // birth heights are the same for btc and ltc regtests 150 } 151 resync = true 152 } 153 err = node.LinkBaseWallet(key, conf.Tip, resync, 154 conf.Tower, conf.Litereghost, conf.ChainProxyURL, p) 155 if err != nil { 156 return err 157 } 158 } 159 // try litecoin testnet4 160 if !lnutil.NopeString(conf.Lt4host) { 161 p := &coinparam.LiteCoinTestNet4Params 162 resync := false 163 conf.Tip = p.StartHeight 164 if conf.Resync == "ltctn" { 165 if conf.Tip < 1 { 166 conf.Tip = 1 167 } 168 resync = true 169 } 170 err = node.LinkBaseWallet( 171 key, p.StartHeight, resync, conf.Tower, 172 conf.Lt4host, conf.ChainProxyURL, p) 173 if err != nil { 174 return err 175 } 176 } 177 // try vertcoin testnet 178 if !lnutil.NopeString(conf.Tvtchost) { 179 p := &coinparam.VertcoinTestNetParams 180 resync := false 181 if conf.Resync == "vtctn" { 182 resync = true 183 } 184 err = node.LinkBaseWallet( 185 key, consts.VertcoinTestnetBHeight, resync, conf.Tower, 186 conf.Tvtchost, conf.ChainProxyURL, p) 187 if err != nil { 188 return err 189 } 190 } 191 // try vertcoin mainnet 192 if !lnutil.NopeString(conf.Vtchost) { 193 p := &coinparam.VertcoinParams 194 resync := false 195 conf.Tip = p.StartHeight 196 if conf.Resync == "ltctn" { 197 if conf.Tip < 1 { 198 conf.Tip = 1 199 } 200 resync = true 201 } 202 err = node.LinkBaseWallet( 203 key, conf.Tip, resync, conf.Tower, 204 conf.Vtchost, conf.ChainProxyURL, p) 205 if err != nil { 206 return err 207 } 208 } 209 // try dummyusd 210 if !lnutil.NopeString(conf.Dummyusdhost) { 211 p := &coinparam.DummyUsdNetParams 212 logging.Infof("Dummyusd: %s\n", conf.Dummyusdhost) 213 resync := false 214 conf.Tip = p.StartHeight 215 if conf.Resync == "dusd" { 216 if conf.Tip < 1 { 217 conf.Tip = 1 218 } 219 resync = true 220 } 221 err = node.LinkBaseWallet(key, consts.BitcoinRegtestBHeight, resync, 222 conf.Tower, conf.Dummyusdhost, conf.ChainProxyURL, p) 223 if err != nil { 224 return err 225 } 226 } 227 228 // try vertcoin regtest 229 if !lnutil.NopeString(conf.Rtvtchost) { 230 p := &coinparam.VertcoinRegTestParams 231 resync := false 232 conf.Tip = p.StartHeight 233 if conf.Resync == "rtvtc" { 234 if conf.Tip < 1 { 235 conf.Tip = 1 236 } 237 resync = true 238 } 239 240 err = node.LinkBaseWallet( 241 key, consts.BitcoinRegtestBHeight, resync, conf.Tower, 242 conf.Rtvtchost, conf.ChainProxyURL, p) 243 if err != nil { 244 return err 245 } 246 } 247 return nil 248 } 249 250 func main() { 251 252 conf := litConfig{ 253 LitHomeDir: defaultLitHomeDirName, 254 Rpcport: defaultRpcport, 255 Rpchost: defaultRpchost, 256 TrackerURL: defaultTrackerURL, 257 AutoReconnect: defaultAutoReconnect, 258 NoAutoListen: defaultNoAutoListen, 259 AutoListenPort: defaultAutoListenPort, 260 AutoReconnectInterval: defaultAutoReconnectInterval, 261 AutoReconnectOnlyConnectedCoins: defaultAutoReconnectOnlyConnectedCoins, 262 UnauthRPC: defaultUnauthRPC, 263 } 264 265 key := litSetup(&conf) 266 if conf.ProxyURL != "" { 267 conf.LitProxyURL = conf.ProxyURL 268 conf.ChainProxyURL = conf.ProxyURL 269 } 270 271 // SIGQUIT handler for debugging 272 go func() { 273 sigs := make(chan os.Signal, 1) 274 signal.Notify(sigs, syscall.SIGQUIT) 275 buf := make([]byte, 1<<20) 276 for { 277 <-sigs 278 stacklen := runtime.Stack(buf, true) 279 logging.Warnf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf[:stacklen]) 280 } 281 }() 282 283 // Setup LN node. Activate Tower if in hard mode. 284 // give node and below file pathof lit home directory 285 node, err := qln.NewLitNode(key, conf.LitHomeDir, conf.TrackerURL, conf.LitProxyURL, conf.Nat) 286 if err != nil { 287 logging.Fatal(err) 288 } 289 290 // node is up; link wallets based on args 291 err = linkWallets(node, key, &conf) 292 if err != nil { 293 // if we don't link wallet, we can still continue, no worries. 294 logging.Error(err) 295 } 296 297 rpcl := new(litrpc.LitRPC) 298 rpcl.Node = node 299 rpcl.OffButton = make(chan bool, 1) 300 node.RPC = rpcl 301 302 // "conf.UnauthRPC" enables unauthenticated Websocket RPC. Default - false. 303 if conf.UnauthRPC { 304 go litrpc.RPCListen(rpcl, conf.Rpchost, conf.Rpcport) 305 } 306 307 // conf.AutoReconnect Attempts to automatically reconnect to known peers periodically. Default - true 308 // conf.NoAutoListen Don't automatically listen on any ports. Default - false 309 if conf.AutoReconnect && !conf.NoAutoListen { 310 node.AutoReconnect(conf.AutoListenPort, conf.AutoReconnectInterval, conf.AutoReconnectOnlyConnectedCoins) 311 } 312 313 <-rpcl.OffButton 314 logging.Infof("Got stop request\n") 315 time.Sleep(time.Second) 316 317 return 318 // New directory being created over at PWD 319 // conf file being created at / 320 }