github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/cmd/di.go (about) 1 /* 2 * Copyright (C) 2018 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package cmd 19 20 import ( 21 "fmt" 22 "net" 23 "net/http" 24 "net/url" 25 "path/filepath" 26 "reflect" 27 "time" 28 29 "github.com/ethereum/go-ethereum/accounts/keystore" 30 "github.com/ethereum/go-ethereum/common" 31 "github.com/pkg/errors" 32 "github.com/rs/zerolog/log" 33 34 "github.com/mysteriumnetwork/node/communication/nats" 35 "github.com/mysteriumnetwork/node/config" 36 "github.com/mysteriumnetwork/node/consumer/migration" 37 consumer_session "github.com/mysteriumnetwork/node/consumer/session" 38 "github.com/mysteriumnetwork/node/core/auth" 39 "github.com/mysteriumnetwork/node/core/beneficiary" 40 "github.com/mysteriumnetwork/node/core/connection" 41 "github.com/mysteriumnetwork/node/core/connection/connectionstate" 42 "github.com/mysteriumnetwork/node/core/discovery" 43 "github.com/mysteriumnetwork/node/core/discovery/proposal" 44 "github.com/mysteriumnetwork/node/core/ip" 45 "github.com/mysteriumnetwork/node/core/location" 46 "github.com/mysteriumnetwork/node/core/monitoring" 47 "github.com/mysteriumnetwork/node/core/node" 48 nodevent "github.com/mysteriumnetwork/node/core/node/event" 49 "github.com/mysteriumnetwork/node/core/policy" 50 "github.com/mysteriumnetwork/node/core/policy/localcopy" 51 "github.com/mysteriumnetwork/node/core/port" 52 "github.com/mysteriumnetwork/node/core/quality" 53 "github.com/mysteriumnetwork/node/core/service" 54 "github.com/mysteriumnetwork/node/core/state" 55 "github.com/mysteriumnetwork/node/core/storage/boltdb" 56 "github.com/mysteriumnetwork/node/core/storage/boltdb/migrations/history" 57 "github.com/mysteriumnetwork/node/core/storage/boltdb/migrator" 58 "github.com/mysteriumnetwork/node/dns" 59 "github.com/mysteriumnetwork/node/eventbus" 60 "github.com/mysteriumnetwork/node/feedback" 61 "github.com/mysteriumnetwork/node/firewall" 62 "github.com/mysteriumnetwork/node/identity" 63 "github.com/mysteriumnetwork/node/identity/registry" 64 identity_selector "github.com/mysteriumnetwork/node/identity/selector" 65 "github.com/mysteriumnetwork/node/logconfig" 66 "github.com/mysteriumnetwork/node/market/mysterium" 67 "github.com/mysteriumnetwork/node/metadata" 68 "github.com/mysteriumnetwork/node/mmn" 69 "github.com/mysteriumnetwork/node/nat" 70 natprobe "github.com/mysteriumnetwork/node/nat/behavior" 71 "github.com/mysteriumnetwork/node/nat/event" 72 "github.com/mysteriumnetwork/node/nat/mapping" 73 "github.com/mysteriumnetwork/node/nat/upnp" 74 "github.com/mysteriumnetwork/node/p2p" 75 "github.com/mysteriumnetwork/node/pilvytis" 76 "github.com/mysteriumnetwork/node/requests" 77 "github.com/mysteriumnetwork/node/requests/resolver" 78 "github.com/mysteriumnetwork/node/router" 79 service_noop "github.com/mysteriumnetwork/node/services/noop" 80 service_openvpn "github.com/mysteriumnetwork/node/services/openvpn" 81 "github.com/mysteriumnetwork/node/services/wireguard/endpoint" 82 "github.com/mysteriumnetwork/node/session/connectivity" 83 "github.com/mysteriumnetwork/node/session/pingpong" 84 "github.com/mysteriumnetwork/node/sleep" 85 "github.com/mysteriumnetwork/node/tequilapi" 86 "github.com/mysteriumnetwork/node/tequilapi/sso" 87 "github.com/mysteriumnetwork/node/ui/versionmanager" 88 "github.com/mysteriumnetwork/node/utils/netutil" 89 paymentClient "github.com/mysteriumnetwork/payments/client" 90 psort "github.com/mysteriumnetwork/payments/client/sort" 91 "github.com/mysteriumnetwork/payments/observer" 92 ) 93 94 // UIServer represents our web server 95 type UIServer interface { 96 Serve() 97 SwitchUI(path string) 98 Stop() 99 } 100 101 // Dependencies is DI container for top level components which is reused in several places 102 type Dependencies struct { 103 Node *Node 104 105 HTTPTransport *http.Transport 106 HTTPClient *requests.HTTPClient 107 108 NetworkDefinition metadata.NetworkDefinition 109 MysteriumAPI *mysterium.MysteriumAPI 110 PricingHelper *pingpong.Pricer 111 EtherClientL1 *paymentClient.EthMultiClient 112 EtherClientL2 *paymentClient.EthMultiClient 113 114 SorterClientL1 *psort.MultiClientSorter 115 SorterClientL2 *psort.MultiClientSorter 116 117 EtherClients []*paymentClient.ReconnectableEthClient 118 119 BrokerConnector *nats.BrokerConnector 120 BrokerConnection nats.Connection 121 122 NATService nat.NATService 123 NATProber natprobe.NATProber 124 Storage *boltdb.Bolt 125 Keystore *identity.Keystore 126 IdentityManager identity.Manager 127 SignerFactory identity.SignerFactory 128 IdentityRegistry registry.IdentityRegistry 129 IdentitySelector identity_selector.Handler 130 IdentityMover *identity.Mover 131 FreeRegistrar *registry.FreeRegistrar 132 133 DiscoveryFactory service.DiscoveryFactory 134 ProposalRepository *discovery.PricedServiceProposalRepository 135 FilterPresetStorage *proposal.FilterPresetStorage 136 DiscoveryWorker discovery.Worker 137 138 QualityClient *quality.MysteriumMORQA 139 140 IPResolver ip.Resolver 141 LocationResolver *location.Cache 142 143 dnsProxy *dns.Proxy 144 145 PolicyOracle *localcopy.Oracle 146 PolicyProvider policy.Provider 147 148 SessionStorage *consumer_session.Storage 149 SessionConnectivityStatusStorage connectivity.StatusStorage 150 151 EventBus eventbus.EventBus 152 153 MultiConnectionManager connection.MultiManager 154 ConnectionRegistry *connection.Registry 155 156 ServicesManager *service.Manager 157 ServiceRegistry *service.Registry 158 ServiceSessions *service.SessionPool 159 ServiceFirewall firewall.IncomingTrafficFirewall 160 161 WireguardClientFactory *endpoint.WgClientFactory 162 163 PortPool *port.Pool 164 PortMapper mapping.PortMapper 165 166 StateKeeper *state.Keeper 167 168 P2PDialer p2p.Dialer 169 P2PListener p2p.Listener 170 171 Authenticator *auth.Authenticator 172 JWTAuthenticator *auth.JWTAuthenticator 173 UIServer UIServer 174 Transactor *registry.Transactor 175 Affiliator *registry.Affiliator 176 BCHelper *paymentClient.MultichainBlockchainClient 177 SSOMystnodes *sso.Mystnodes 178 179 LogCollector *logconfig.Collector 180 Reporter *feedback.Reporter 181 182 BeneficiarySaver *beneficiary.Saver 183 BeneficiaryProvider *beneficiary.Provider 184 185 ProviderInvoiceStorage *pingpong.ProviderInvoiceStorage 186 ConsumerTotalsStorage *pingpong.ConsumerTotalsStorage 187 HermesPromiseStorage *pingpong.HermesPromiseStorage 188 ConsumerBalanceTracker *pingpong.ConsumerBalanceTracker 189 HermesChannelRepository *pingpong.HermesChannelRepository 190 HermesPromiseSettler pingpong.HermesPromiseSettler 191 HermesURLGetter *pingpong.HermesURLGetter 192 HermesCaller *pingpong.HermesCaller 193 HermesPromiseHandler *pingpong.HermesPromiseHandler 194 SettlementHistoryStorage *pingpong.SettlementHistoryStorage 195 AddressProvider *paymentClient.MultiChainAddressProvider 196 HermesStatusChecker *pingpong.HermesStatusChecker 197 HermesMigrator *migration.HermesMigrator 198 199 MMN *mmn.MMN 200 201 PilvytisAPI *pilvytis.API 202 PilvytisTracker *pilvytis.StatusTracker 203 PilvytisOrderIssuer *pilvytis.OrderIssuer 204 205 ObserverAPI *observer.API 206 207 ResidentCountry *identity.ResidentCountry 208 209 BeneficiaryAddressStorage beneficiary.BeneficiaryStorage 210 NodeStatusTracker *monitoring.StatusTracker 211 NodeStatsTracker *node.StatsTracker 212 uiVersionConfig versionmanager.NodeUIVersionConfig 213 } 214 215 // Bootstrap initiates all container dependencies 216 func (di *Dependencies) Bootstrap(nodeOptions node.Options) error { 217 logconfig.Configure(&nodeOptions.LogOptions) 218 219 netutil.LogNetworkStats() 220 221 p2p.RegisterContactUnserializer() 222 223 log.Info().Msg("Starting Mysterium Node " + metadata.VersionAsString()) 224 225 // Check early for presence of an already running node 226 tequilaListener, err := di.createTequilaListener(nodeOptions) 227 if err != nil { 228 return err 229 } 230 231 if err := nodeOptions.Directories.Check(); err != nil { 232 return err 233 } 234 235 if err := di.bootstrapFirewall(nodeOptions.Firewall); err != nil { 236 return err 237 } 238 239 di.bootstrapEventBus() 240 241 if err := di.bootstrapStorage(nodeOptions.Directories.Storage); err != nil { 242 return err 243 } 244 245 if err := di.bootstrapNetworkComponents(nodeOptions); err != nil { 246 return err 247 } 248 249 if err := di.bootstrapLocationComponents(nodeOptions); err != nil { 250 return err 251 } 252 if err := di.bootstrapResidentCountry(); err != nil { 253 return err 254 } 255 if err := di.bootstrapIdentityComponents(nodeOptions); err != nil { 256 return err 257 } 258 259 if err := di.bootstrapDiscoveryComponents(nodeOptions.Discovery); err != nil { 260 return err 261 } 262 263 if err := di.bootstrapAuthenticator(); err != nil { 264 return err 265 } 266 267 if err := di.bootstrapNodeUIVersionConfig(nodeOptions); err != nil { 268 return err 269 } 270 271 di.bootstrapUIServer(nodeOptions) 272 if err := di.bootstrapMMN(); err != nil { 273 return err 274 } 275 276 portRange, err := getUDPListenPorts() 277 if err != nil { 278 return err 279 } 280 281 di.PortPool = port.NewFixedRangePool(portRange) 282 283 di.bootstrapP2P() 284 di.SessionConnectivityStatusStorage = connectivity.NewStatusStorage() 285 286 if err := di.bootstrapServices(nodeOptions); err != nil { 287 return err 288 } 289 290 if err := di.bootstrapQualityComponents(nodeOptions.Quality); err != nil { 291 return err 292 } 293 294 if err := di.bootstrapNodeComponents(nodeOptions, tequilaListener); err != nil { 295 return err 296 } 297 298 di.registerConnections(nodeOptions) 299 if err = di.handleConnStateChange(); err != nil { 300 return err 301 } 302 if err := di.Node.Start(); err != nil { 303 return err 304 } 305 306 config.Current.EnableEventPublishing(di.EventBus) 307 308 di.handleNATStatusForPublicIP() 309 310 log.Info().Msg("Mysterium node started!") 311 return nil 312 } 313 314 func (di *Dependencies) bootstrapAddressProvider(nodeOptions node.Options) { 315 ch1 := nodeOptions.Chains.Chain1 316 ch2 := nodeOptions.Chains.Chain2 317 chain1KnownHermeses := parseAddressSlice(ch1.KnownHermeses) 318 chain2KnownHermeses := parseAddressSlice(ch2.KnownHermeses) 319 hermesAddresses, err := di.ObserverAPI.GetApprovedHermesAdresses() 320 if err != nil { 321 log.Warn().AnErr("err", err).Msg("observer hermeses call failed, using fallback known hermeses") 322 } else { 323 chain1ApprovedHermeses, ok := hermesAddresses[ch1.ChainID] 324 if ok { 325 chain1KnownHermeses = chain1ApprovedHermeses 326 } 327 chain2ApprovedHermeses, ok := hermesAddresses[ch2.ChainID] 328 if ok { 329 chain2KnownHermeses = chain2ApprovedHermeses 330 } 331 } 332 addresses := map[int64]paymentClient.SmartContractAddresses{ 333 ch1.ChainID: { 334 Registry: common.HexToAddress(ch1.RegistryAddress), 335 Myst: common.HexToAddress(ch1.MystAddress), 336 ActiveHermes: common.HexToAddress(ch1.HermesID), 337 ActiveChannelImplementation: common.HexToAddress(ch1.ChannelImplAddress), 338 KnownHermeses: chain1KnownHermeses, 339 }, 340 ch2.ChainID: { 341 Registry: common.HexToAddress(ch2.RegistryAddress), 342 Myst: common.HexToAddress(ch2.MystAddress), 343 ActiveHermes: common.HexToAddress(ch2.HermesID), 344 ActiveChannelImplementation: common.HexToAddress(ch2.ChannelImplAddress), 345 KnownHermeses: chain2KnownHermeses, 346 }, 347 } 348 349 keeper := paymentClient.NewMultiChainAddressKeeper(addresses) 350 di.AddressProvider = paymentClient.NewMultiChainAddressProvider(keeper, di.BCHelper) 351 } 352 353 func (di *Dependencies) bootstrapP2P() { 354 verifierFactory := func(id identity.Identity) identity.Verifier { 355 return identity.NewVerifierIdentity(id) 356 } 357 358 di.P2PListener = p2p.NewListener(di.BrokerConnection, di.SignerFactory, identity.NewVerifierSigned(), di.IPResolver, di.EventBus) 359 di.P2PDialer = p2p.NewDialer(di.BrokerConnector, di.SignerFactory, verifierFactory, di.IPResolver, di.PortPool, di.EventBus) 360 } 361 362 func (di *Dependencies) createTequilaListener(nodeOptions node.Options) (net.Listener, error) { 363 if !nodeOptions.TequilapiEnabled { 364 return tequilapi.NewNoopListener() 365 } 366 367 tequilaListener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", nodeOptions.TequilapiAddress, nodeOptions.TequilapiPort)) 368 if err != nil { 369 return nil, errors.Wrap(err, fmt.Sprintf("the port %v seems to be taken. Either you're already running a node or it is already used by another application", nodeOptions.TequilapiPort)) 370 } 371 return tequilaListener, nil 372 } 373 374 func (di *Dependencies) bootstrapStateKeeper(options node.Options) error { 375 deps := state.KeeperDeps{ 376 Publisher: di.EventBus, 377 ServiceLister: di.ServicesManager, 378 IdentityProvider: di.IdentityManager, 379 IdentityRegistry: di.IdentityRegistry, 380 IdentityChannelCalculator: di.AddressProvider, 381 BalanceProvider: di.ConsumerBalanceTracker, 382 EarningsProvider: di.HermesChannelRepository, 383 ChainID: options.ChainID, 384 ProposalPricer: di.ProposalRepository, 385 } 386 387 di.StateKeeper = state.NewKeeper(deps, state.DefaultDebounceDuration) 388 if options.SSE.Enabled { 389 return di.StateKeeper.Subscribe(di.EventBus) 390 } 391 392 return nil 393 } 394 395 func (di *Dependencies) registerOpenvpnConnection(nodeOptions node.Options) { 396 service_openvpn.Bootstrap() 397 connectionFactory := func() (connection.Connection, error) { 398 return service_openvpn.NewClient( 399 // TODO instead of passing binary path here, Openvpn from node options could represent abstract vpn factory itself 400 nodeOptions.Openvpn.BinaryPath(), 401 nodeOptions.Directories.Script, 402 nodeOptions.Directories.Runtime, 403 di.SignerFactory, 404 di.IPResolver, 405 ) 406 } 407 di.ConnectionRegistry.Register(service_openvpn.ServiceType, connectionFactory) 408 } 409 410 func (di *Dependencies) registerNoopConnection() { 411 service_noop.Bootstrap() 412 di.ConnectionRegistry.Register(service_noop.ServiceType, service_noop.NewConnection) 413 } 414 415 // Shutdown stops container 416 func (di *Dependencies) Shutdown() (err error) { 417 var errs []error 418 defer func() { 419 for i := range errs { 420 log.Error().Err(errs[i]).Msg("Dependencies shutdown failed") 421 if err == nil { 422 err = errs[i] 423 } 424 } 425 }() 426 427 // Kill node first which includes current active VPN connection cleanup. 428 if di.Node != nil { 429 if err := di.Node.Kill(); err != nil { 430 errs = append(errs, err) 431 } 432 } 433 434 if di.ServicesManager != nil { 435 if err := di.ServicesManager.Kill(); err != nil { 436 errs = append(errs, err) 437 } 438 } 439 440 if di.PolicyOracle != nil { 441 di.PolicyOracle.Stop() 442 } 443 444 if di.NATService != nil { 445 if err := di.NATService.Disable(); err != nil { 446 errs = append(errs, err) 447 } 448 } 449 450 if di.EtherClientL1 != nil { 451 di.EtherClientL1.Close() 452 } 453 if di.SorterClientL1 != nil { 454 di.SorterClientL1.Stop() 455 } 456 457 if di.EtherClientL2 != nil { 458 di.EtherClientL2.Close() 459 } 460 if di.SorterClientL2 != nil { 461 di.SorterClientL2.Stop() 462 } 463 464 if di.DiscoveryWorker != nil { 465 di.DiscoveryWorker.Stop() 466 } 467 if di.PilvytisTracker != nil { 468 di.PilvytisTracker.Stop() 469 } 470 if di.BrokerConnection != nil { 471 di.BrokerConnection.Close() 472 } 473 474 if di.QualityClient != nil { 475 di.QualityClient.Stop() 476 } 477 478 if di.ServiceFirewall != nil { 479 di.ServiceFirewall.Teardown() 480 } 481 firewall.Reset() 482 483 if di.Storage != nil { 484 if err := di.Storage.Close(); err != nil { 485 errs = append(errs, err) 486 } 487 } 488 489 router.Clean() 490 491 return nil 492 } 493 494 func (di *Dependencies) bootstrapStorage(path string) error { 495 localStorage, err := boltdb.NewStorage(path) 496 if err != nil { 497 return err 498 } 499 500 migrator := migrator.NewMigrator(localStorage) 501 err = migrator.RunMigrations(history.Sequence) 502 if err != nil { 503 return err 504 } 505 506 di.Storage = localStorage 507 508 invoiceStorage := pingpong.NewInvoiceStorage(di.Storage) 509 di.ProviderInvoiceStorage = pingpong.NewProviderInvoiceStorage(invoiceStorage) 510 di.ConsumerTotalsStorage = pingpong.NewConsumerTotalsStorage(di.EventBus) 511 di.HermesPromiseStorage = pingpong.NewHermesPromiseStorage(di.Storage) 512 di.SessionStorage = consumer_session.NewSessionStorage(di.Storage) 513 di.SettlementHistoryStorage = pingpong.NewSettlementHistoryStorage(di.Storage) 514 return di.SessionStorage.Subscribe(di.EventBus) 515 } 516 517 func (di *Dependencies) getHermesURL(nodeOptions node.Options) (string, error) { 518 log.Info().Msgf("Node chain id %v", nodeOptions.ChainID) 519 addr := common.HexToAddress(nodeOptions.Chains.Chain2.HermesID) 520 if nodeOptions.ChainID == nodeOptions.Chains.Chain1.ChainID { 521 addr = common.HexToAddress(nodeOptions.Chains.Chain1.HermesID) 522 } 523 524 hermesURL, err := di.HermesURLGetter.GetHermesURL(nodeOptions.ChainID, addr) 525 if err != nil { 526 return "", fmt.Errorf("could not get hermes URL: %w", err) 527 } 528 return hermesURL, nil 529 } 530 531 func (di *Dependencies) bootstrapNodeComponents(nodeOptions node.Options, tequilaListener net.Listener) error { 532 di.ConsumerBalanceTracker = pingpong.NewConsumerBalanceTracker( 533 di.EventBus, 534 di.BCHelper, 535 di.ConsumerTotalsStorage, 536 di.HermesCaller, 537 di.Transactor, 538 di.IdentityRegistry, 539 di.AddressProvider, 540 di.BCHelper, 541 pingpong.ConsumerBalanceTrackerConfig{ 542 FastSync: pingpong.PollConfig{ 543 Interval: nodeOptions.Payments.BalanceFastPollInterval, 544 Timeout: nodeOptions.Payments.BalanceFastPollTimeout, 545 }, 546 LongSync: pingpong.PollConfig{ 547 Interval: nodeOptions.Payments.BalanceLongPollInterval, 548 }, 549 }, 550 ) 551 552 err := di.ConsumerBalanceTracker.Subscribe(di.EventBus) 553 if err != nil { 554 return errors.Wrap(err, "could not subscribe consumer balance tracker to relevant events") 555 } 556 557 di.BeneficiaryAddressStorage = beneficiary.NewAddressStorage(di.Storage) 558 di.bootstrapBeneficiaryProvider(nodeOptions) 559 560 di.HermesPromiseHandler = pingpong.NewHermesPromiseHandler(pingpong.HermesPromiseHandlerDeps{ 561 HermesPromiseStorage: di.HermesPromiseStorage, 562 HermesCallerFactory: func(hermesURL string) pingpong.HermesHTTPRequester { 563 return pingpong.NewHermesCaller(di.HTTPClient, hermesURL) 564 }, 565 HermesURLGetter: di.HermesURLGetter, 566 FeeProvider: di.Transactor, 567 Encryption: di.Keystore, 568 EventBus: di.EventBus, 569 Signer: di.SignerFactory, 570 Chains: []int64{nodeOptions.Chains.Chain1.ChainID, nodeOptions.Chains.Chain2.ChainID}, 571 }) 572 573 if err := di.HermesPromiseHandler.Subscribe(di.EventBus); err != nil { 574 return err 575 } 576 577 if err := di.bootstrapHermesPromiseSettler(nodeOptions); err != nil { 578 return err 579 } 580 581 di.bootstrapBeneficiarySaver(nodeOptions) 582 583 di.ConnectionRegistry = connection.NewRegistry() 584 di.MultiConnectionManager = connection.NewMultiConnectionManager(func() connection.Manager { 585 return connection.NewManager( 586 pingpong.ExchangeFactoryFunc( 587 di.Keystore, 588 di.SignerFactory, 589 di.ConsumerTotalsStorage, 590 di.AddressProvider, 591 di.EventBus, 592 nodeOptions.Payments.ConsumerDataLeewayMegabytes, 593 ), 594 di.ConnectionRegistry.CreateConnection, 595 di.EventBus, 596 di.IPResolver, 597 di.LocationResolver, 598 connection.DefaultConfig(), 599 config.GetDuration(config.FlagStatsReportInterval), 600 connection.NewValidator( 601 di.ConsumerBalanceTracker, 602 di.IdentityManager, 603 ), 604 di.P2PDialer, 605 di.allowTrustedDomainBypassTunnel, 606 di.disallowTrustedDomainBypassTunnel, 607 ) 608 }) 609 610 di.NATProber = natprobe.NewNATProber(di.MultiConnectionManager, di.EventBus) 611 612 di.LogCollector = logconfig.NewCollector(&logconfig.CurrentLogOptions) 613 reporter, err := feedback.NewReporter(di.LogCollector, di.IdentityManager, di.LocationResolver, nodeOptions.FeedbackURL) 614 if err != nil { 615 return err 616 } 617 di.Reporter = reporter 618 619 if err := di.bootstrapStateKeeper(nodeOptions); err != nil { 620 return err 621 } 622 623 di.bootstrapPilvytis(nodeOptions) 624 625 di.NodeStatusTracker = monitoring.NewStatusTracker( 626 di.IdentityManager, 627 di.QualityClient, 628 ) 629 630 di.NodeStatsTracker = node.NewNodeStatsTracker( 631 di.QualityClient.ProviderStatuses, 632 di.QualityClient.ProviderSessionsList, 633 di.QualityClient.ProviderTransferredData, 634 di.QualityClient.ProviderSessionsCount, 635 di.QualityClient.ProviderConsumersCount, 636 di.QualityClient.ProviderEarningsSeries, 637 di.QualityClient.ProviderSessionsSeries, 638 di.QualityClient.ProviderTransferredDataSeries, 639 di.QualityClient.ProviderActivityStats, 640 di.QualityClient.ProviderQuality, 641 di.QualityClient.ProviderServiceEarnings, 642 di.IdentityManager, 643 ) 644 645 di.HermesMigrator = di.bootstrapHermesMigrator() 646 if err := di.HermesMigrator.Subscribe(di.EventBus); err != nil { 647 return fmt.Errorf("error during subscribe: %w", err) 648 } 649 650 tequilapiHTTPServer, err := di.bootstrapTequilapi(nodeOptions, tequilaListener) 651 if err != nil { 652 return err 653 } 654 655 sleepNotifier := sleep.NewNotifier(di.MultiConnectionManager, di.EventBus) 656 sleepNotifier.Subscribe() 657 658 di.Node = NewNode(di.MultiConnectionManager, tequilapiHTTPServer, di.EventBus, di.UIServer, sleepNotifier) 659 660 return nil 661 } 662 663 // function decides on network definition combined from testnet3/localnet flags and possible overrides 664 func (di *Dependencies) bootstrapNetworkComponents(options node.Options) (err error) { 665 optionsNetwork := options.OptionsNetwork 666 network := metadata.DefaultNetwork 667 668 switch { 669 case optionsNetwork.Network.IsMainnet(): 670 network = metadata.MainnetDefinition 671 case optionsNetwork.Network.IsLocalnet(): 672 network = metadata.LocalnetDefinition 673 case optionsNetwork.Network.IsTestnet(): 674 network = metadata.TestnetDefinition 675 } 676 677 // override defined values one by one from options 678 if optionsNetwork.DiscoveryAddress != metadata.DefaultNetwork.DiscoveryAddress { 679 network.DiscoveryAddress = optionsNetwork.DiscoveryAddress 680 } 681 682 if !reflect.DeepEqual(optionsNetwork.BrokerAddresses, metadata.DefaultNetwork.BrokerAddresses) { 683 network.BrokerAddresses = optionsNetwork.BrokerAddresses 684 } 685 686 if fmt.Sprint(optionsNetwork.EtherClientRPCL1) != fmt.Sprint(metadata.DefaultNetwork.Chain1.EtherClientRPC) { 687 network.Chain1.EtherClientRPC = optionsNetwork.EtherClientRPCL1 688 } 689 if fmt.Sprint(optionsNetwork.EtherClientRPCL2) != fmt.Sprint(metadata.DefaultNetwork.Chain2.EtherClientRPC) { 690 network.Chain2.EtherClientRPC = optionsNetwork.EtherClientRPCL2 691 } 692 693 di.NetworkDefinition = network 694 695 dnsMap := optionsNetwork.DNSMap 696 for host, hostIPs := range network.DNSMap { 697 dnsMap[host] = append(dnsMap[host], hostIPs...) 698 } 699 for host, hostIPs := range dnsMap { 700 log.Info().Msgf("Using local DNS: %s -> %s", host, hostIPs) 701 } 702 resolver := resolver.NewResolverMap(dnsMap) 703 704 dialer := requests.NewDialerSwarm(options.BindAddress, options.SwarmDialerDNSHeadstart) 705 dialer.ResolveContext = resolver 706 di.HTTPTransport = requests.NewTransport(dialer.DialContext) 707 di.HTTPClient = requests.NewHTTPClientWithTransport(di.HTTPTransport, requests.DefaultTimeout) 708 di.MysteriumAPI = mysterium.NewClient(di.HTTPClient, network.DiscoveryAddress) 709 di.PricingHelper = pingpong.NewPricer(di.MysteriumAPI) 710 err = di.PricingHelper.Subscribe(di.EventBus) 711 if err != nil { 712 return err 713 } 714 715 brokerURLs := make([]*url.URL, len(di.NetworkDefinition.BrokerAddresses)) 716 for i, brokerAddress := range di.NetworkDefinition.BrokerAddresses { 717 brokerURL, err := nats.ParseServerURL(brokerAddress) 718 if err != nil { 719 return err 720 } 721 brokerURLs[i] = brokerURL 722 } 723 724 di.BrokerConnector = nats.NewBrokerConnector(dialer.DialContext, resolver) 725 if di.BrokerConnection, err = di.BrokerConnector.Connect(brokerURLs...); err != nil { 726 return err 727 } 728 729 log.Info().Msgf("Using L1 Eth endpoints: %v", network.Chain1.EtherClientRPC) 730 log.Info().Msgf("Using L2 Eth endpoints: %v", network.Chain2.EtherClientRPC) 731 732 di.EtherClients = make([]*paymentClient.ReconnectableEthClient, 0) 733 bcClientsL1 := make([]paymentClient.AddressableEthClientGetter, 0) 734 for _, rpc := range network.Chain1.EtherClientRPC { 735 client, err := paymentClient.NewReconnectableEthClient(rpc, time.Second*10) 736 if err != nil { 737 log.Warn().Msgf("failed to load rpc endpoint: %s", rpc) 738 continue 739 } 740 di.EtherClients = append(di.EtherClients, client) 741 bcClientsL1 = append(bcClientsL1, client) 742 } 743 744 if len(bcClientsL1) == 0 { 745 log.Error().Msg("no l1 rpc endpoints loaded") 746 } 747 748 bcClientsL2 := make([]paymentClient.AddressableEthClientGetter, 0) 749 for _, rpc := range network.Chain2.EtherClientRPC { 750 client, err := paymentClient.NewReconnectableEthClient(rpc, time.Second*10) 751 if err != nil { 752 log.Warn().Msgf("failed to load rpc endpoint: %s", rpc) 753 continue 754 } 755 756 di.EtherClients = append(di.EtherClients, client) 757 bcClientsL2 = append(bcClientsL2, client) 758 } 759 760 if len(bcClientsL2) == 0 { 761 log.Error().Msg("no l1 rpc endpoints loaded") 762 } 763 764 notifyChannelL1 := make(chan paymentClient.Notification, 5) 765 di.EtherClientL1, err = paymentClient.NewEthMultiClientNotifyDown(time.Second*20, bcClientsL1, notifyChannelL1) 766 if err != nil { 767 return err 768 } 769 di.SorterClientL1 = psort.NewMultiClientSorterNoTicker(di.EtherClientL1, notifyChannelL1) 770 di.SorterClientL1.AddOnNotificationAction(psort.DefaultByAvailability) 771 go di.SorterClientL1.Run() 772 773 notifyChannelL2 := make(chan paymentClient.Notification, 5) 774 di.EtherClientL2, err = paymentClient.NewEthMultiClientNotifyDown(time.Second*20, bcClientsL2, notifyChannelL2) 775 if err != nil { 776 return err 777 } 778 di.SorterClientL2 = psort.NewMultiClientSorterNoTicker(di.EtherClientL2, notifyChannelL2) 779 di.SorterClientL2.AddOnNotificationAction(psort.DefaultByAvailability) 780 go di.SorterClientL2.Run() 781 782 bcL1 := paymentClient.NewBlockchain(di.EtherClientL1, options.Payments.BCTimeout) 783 bcL2 := paymentClient.NewBlockchain(di.EtherClientL2, options.Payments.BCTimeout) 784 785 clients := make(map[int64]paymentClient.BC) 786 clients[options.Chains.Chain1.ChainID] = bcL1 787 clients[options.Chains.Chain2.ChainID] = bcL2 788 789 di.BCHelper = paymentClient.NewMultichainBlockchainClient(clients) 790 di.ObserverAPI = observer.NewAPI(options.ObserverAddress, time.Second*30) 791 di.bootstrapAddressProvider(options) 792 di.HermesURLGetter = pingpong.NewHermesURLGetter(di.BCHelper, di.AddressProvider, di.ObserverAPI) 793 794 registryStorage := registry.NewRegistrationStatusStorage(di.Storage) 795 796 hermesURL, err := di.getHermesURL(options) 797 if err != nil { 798 return err 799 } 800 801 di.HermesCaller = pingpong.NewHermesCaller(di.HTTPClient, hermesURL) 802 di.SignerFactory = func(id identity.Identity) identity.Signer { 803 return identity.NewSigner(di.Keystore, id) 804 } 805 806 if err := di.bootstrapSSOMystnodes(); err != nil { 807 return err 808 } 809 810 di.Transactor = registry.NewTransactor( 811 di.HTTPClient, 812 options.Transactor.TransactorEndpointAddress, 813 di.AddressProvider, 814 di.SignerFactory, 815 di.EventBus, 816 di.BCHelper, 817 options.Transactor.TransactorFeesValidTime, 818 ) 819 di.Affiliator = registry.NewAffiliator(di.HTTPClient, options.Affiliator.AffiliatorEndpointAddress) 820 821 registryCfg := registry.IdentityRegistryConfig{ 822 TransactorPollInterval: options.Payments.RegistryTransactorPollInterval, 823 TransactorPollTimeout: options.Payments.RegistryTransactorPollTimeout, 824 } 825 826 if di.IdentityRegistry, err = registry.NewIdentityRegistryContract(di.EtherClientL2, di.AddressProvider, registryStorage, di.EventBus, di.HermesCaller, di.Transactor, di.IdentitySelector, registryCfg); err != nil { 827 return err 828 } 829 830 allow := []string{ 831 network.DiscoveryAddress, 832 options.Transactor.TransactorEndpointAddress, 833 options.Affiliator.AffiliatorEndpointAddress, 834 hermesURL, 835 options.PilvytisAddress, 836 } 837 allow = append(allow, network.Chain1.EtherClientRPC...) 838 allow = append(allow, network.Chain2.EtherClientRPC...) 839 840 if err := di.AllowURLAccess(allow...); err != nil { 841 return err 842 } 843 844 di.WireguardClientFactory = endpoint.NewWGClientFactory() 845 846 return di.IdentityRegistry.Subscribe(di.EventBus) 847 } 848 849 func (di *Dependencies) bootstrapEventBus() { 850 di.EventBus = eventbus.New() 851 } 852 853 func (di *Dependencies) bootstrapIdentityComponents(options node.Options) error { 854 var ks *keystore.KeyStore 855 if options.Keystore.UseLightweight { 856 log.Debug().Msg("Using lightweight keystore") 857 ks = keystore.NewKeyStore(options.Directories.Keystore, keystore.LightScryptN, keystore.LightScryptP) 858 } else { 859 log.Debug().Msg("Using heavyweight keystore") 860 ks = keystore.NewKeyStore(options.Directories.Keystore, keystore.StandardScryptN, keystore.StandardScryptP) 861 } 862 863 di.Keystore = identity.NewKeystoreFilesystem(options.Directories.Keystore, ks) 864 if di.ResidentCountry == nil { 865 return errMissingDependency("di.residentCountry") 866 } 867 di.IdentityManager = identity.NewIdentityManager(di.Keystore, di.EventBus, di.ResidentCountry) 868 869 di.IdentitySelector = identity_selector.NewHandler( 870 di.IdentityManager, 871 identity.NewIdentityCache(options.Directories.Keystore, "remember.json"), 872 di.SignerFactory, 873 ) 874 di.IdentityMover = identity.NewMover( 875 di.Keystore, 876 di.EventBus, 877 di.SignerFactory) 878 879 di.FreeRegistrar = registry.NewFreeRegistrar(di.IdentitySelector, di.Transactor, di.IdentityRegistry, options.Transactor.TryFreeRegistration) 880 if err := di.FreeRegistrar.Subscribe(di.EventBus); err != nil { 881 return err 882 } 883 return nil 884 } 885 886 func (di *Dependencies) bootstrapQualityComponents(options node.OptionsQuality) (err error) { 887 if err := di.AllowURLAccess(options.Address); err != nil { 888 return err 889 } 890 891 di.QualityClient = quality.NewMorqaClient( 892 requests.NewHTTPClientWithTransport(di.HTTPTransport, 60*time.Second), 893 options.Address, 894 di.SignerFactory, 895 ) 896 go di.QualityClient.Start() 897 898 var transport quality.Transport 899 switch options.Type { 900 case node.QualityTypeElastic: 901 transport = quality.NewElasticSearchTransport(di.HTTPClient, options.Address, 10*time.Second) 902 case node.QualityTypeMORQA: 903 transport = quality.NewMORQATransport(di.QualityClient, di.LocationResolver) 904 case node.QualityTypeNone: 905 transport = quality.NewNoopTransport() 906 default: 907 err = errors.Errorf("unknown Quality Oracle provider: %s", options.Type) 908 } 909 if err != nil { 910 return err 911 } 912 913 // Quality metrics 914 qualitySender := quality.NewSender(transport, metadata.VersionAsString()) 915 if err := qualitySender.Subscribe(di.EventBus); err != nil { 916 return err 917 } 918 919 // warm up the loader as the load takes up to a couple of secs 920 loader := &upnp.GatewayLoader{} 921 go loader.Get() 922 natSender := event.NewSender(qualitySender, di.IPResolver.GetPublicIP, loader.HumanReadable) 923 if err := natSender.Subscribe(di.EventBus); err != nil { 924 return err 925 } 926 927 return nil 928 } 929 930 func (di *Dependencies) bootstrapLocationComponents(options node.Options) (err error) { 931 if err = di.AllowURLAccess(options.Location.IPDetectorURL); err != nil { 932 return errors.Wrap(err, "failed to add firewall exception") 933 } 934 935 ipResolver := ip.NewResolver(di.HTTPClient, options.BindAddress, options.Location.IPDetectorURL, ip.IPFallbackAddresses) 936 di.IPResolver = ip.NewCachedResolver(ipResolver, 5*time.Minute) 937 938 var resolver location.Resolver 939 switch options.Location.Type { 940 case node.LocationTypeManual: 941 resolver = location.NewStaticResolver(options.Location.Country, options.Location.City, options.Location.IPType, di.IPResolver) 942 case node.LocationTypeBuiltin: 943 resolver, err = location.NewBuiltInResolver(di.IPResolver) 944 case node.LocationTypeMMDB: 945 resolver, err = location.NewExternalDBResolver(filepath.Join(options.Directories.Script, options.Location.Address), di.IPResolver) 946 case node.LocationTypeOracle: 947 if err := di.AllowURLAccess(options.Location.Address); err != nil { 948 return err 949 } 950 resolver, err = location.NewOracleResolver(di.HTTPClient, options.Location.Address), nil 951 default: 952 err = errors.Errorf("unknown location provider: %s", options.Location.Type) 953 } 954 if err != nil { 955 return err 956 } 957 958 di.LocationResolver = location.NewCache(resolver, di.EventBus, time.Minute*5) 959 960 if !config.GetBool(config.FlagProxyMode) && !config.GetBool(config.FlagDVPNMode) { 961 err = di.EventBus.SubscribeAsync(connectionstate.AppTopicConnectionState, di.LocationResolver.HandleConnectionEvent) 962 if err != nil { 963 return err 964 } 965 } 966 967 err = di.EventBus.SubscribeAsync(nodevent.AppTopicNode, di.LocationResolver.HandleNodeEvent) 968 if err != nil { 969 return err 970 } 971 972 return nil 973 } 974 975 func (di *Dependencies) bootstrapAuthenticator() error { 976 key, err := auth.NewJWTEncryptionKey(di.Storage) 977 if err != nil { 978 return err 979 } 980 di.Authenticator = auth.NewAuthenticator() 981 di.JWTAuthenticator = auth.NewJWTAuthenticator(key) 982 983 return nil 984 } 985 986 func (di *Dependencies) bootstrapPilvytis(options node.Options) { 987 di.PilvytisAPI = pilvytis.NewAPI(di.HTTPClient, options.PilvytisAddress, di.SignerFactory, di.LocationResolver, di.AddressProvider) 988 di.PilvytisTracker = pilvytis.NewStatusTracker(di.PilvytisAPI, di.IdentityManager, di.EventBus, time.Minute) 989 di.PilvytisOrderIssuer = pilvytis.NewOrderIssuer(di.PilvytisAPI, di.PilvytisTracker) 990 991 go di.PilvytisTracker.Track() 992 di.PilvytisTracker.SubscribeAsync(di.EventBus) 993 } 994 995 func (di *Dependencies) bootstrapFirewall(options node.OptionsFirewall) error { 996 firewall.DefaultOutgoingFirewall = firewall.NewOutgoingTrafficFirewall(config.GetBool(config.FlagOutgoingFirewall)) 997 if err := firewall.DefaultOutgoingFirewall.Setup(); err != nil { 998 return err 999 } 1000 1001 di.ServiceFirewall = firewall.NewIncomingTrafficFirewall(config.GetBool(config.FlagIncomingFirewall)) 1002 if err := di.ServiceFirewall.Setup(); err != nil { 1003 return err 1004 } 1005 1006 if options.BlockAlways { 1007 bindAddress := "0.0.0.0" 1008 resolver := ip.NewResolver(di.HTTPClient, bindAddress, "", ip.IPFallbackAddresses) 1009 outboundIP, err := resolver.GetOutboundIP() 1010 if err != nil { 1011 return err 1012 } 1013 1014 _, err = firewall.BlockNonTunnelTraffic(firewall.Global, outboundIP) 1015 return err 1016 } 1017 return nil 1018 } 1019 1020 func (di *Dependencies) bootstrapBeneficiaryProvider(options node.Options) { 1021 di.BeneficiaryProvider = beneficiary.NewProvider( 1022 options.ChainID, 1023 di.AddressProvider, 1024 di.Storage, 1025 di.BCHelper, 1026 ) 1027 } 1028 1029 func (di *Dependencies) bootstrapBeneficiarySaver(options node.Options) { 1030 di.BeneficiarySaver = beneficiary.NewSaver( 1031 options.ChainID, 1032 di.AddressProvider, 1033 di.Storage, 1034 di.BCHelper, 1035 di.HermesPromiseSettler, 1036 ) 1037 } 1038 1039 func (di *Dependencies) bootstrapHermesMigrator() *migration.HermesMigrator { 1040 return migration.NewHermesMigrator( 1041 di.Transactor, 1042 di.AddressProvider, 1043 di.HermesURLGetter, 1044 func(hermesURL string) pingpong.HermesHTTPRequester { 1045 return pingpong.NewHermesCaller(di.HTTPClient, hermesURL) 1046 }, 1047 di.HermesPromiseSettler, 1048 di.IdentityRegistry, 1049 di.ConsumerBalanceTracker, 1050 migration.NewStorage(di.Storage, di.AddressProvider), 1051 di.BCHelper, 1052 ) 1053 } 1054 1055 func (di *Dependencies) bootstrapSSOMystnodes() error { 1056 s := sso.NewMystnodes(di.SignerFactory, di.HTTPClient) 1057 di.SSOMystnodes = s 1058 return s.Subscribe(di.EventBus) 1059 } 1060 1061 func (di *Dependencies) handleConnStateChange() error { 1062 if di.HTTPClient == nil { 1063 return errors.New("HTTPClient is not initialized") 1064 } 1065 1066 latestState := connectionstate.NotConnected 1067 return di.EventBus.SubscribeAsync(connectionstate.AppTopicConnectionState, func(e connectionstate.AppEventConnectionState) { 1068 if config.GetBool(config.FlagProxyMode) || config.GetBool(config.FlagDVPNMode) { 1069 return // Proxy mode doesn't establish system wide tunnels, no reconnect required. 1070 } 1071 1072 // Here we care only about connected and disconnected events. 1073 if e.State != connectionstate.Connected && e.State != connectionstate.NotConnected { 1074 return 1075 } 1076 1077 isDisconnected := latestState == connectionstate.Connected && e.State == connectionstate.NotConnected 1078 isConnected := latestState == connectionstate.NotConnected && e.State == connectionstate.Connected 1079 if isDisconnected || isConnected { 1080 netutil.LogNetworkStats() 1081 1082 log.Info().Msg("Reconnecting HTTP clients due to VPN connection state change") 1083 di.HTTPTransport.CloseIdleConnections() 1084 1085 for _, cl := range di.EtherClients { 1086 if err := cl.Reconnect(time.Second * 15); err != nil { 1087 log.Warn().Err(err).Msg("Ethereum client failed to reconnect, will retry one more time") 1088 // Default golang DNS resolver does not allow to reload /etc/resolv.conf more than once per 5 seconds. 1089 // This could lead to the problem, when right after connect/disconnect new DNS config not applied instantly. 1090 // Doing a couple of retries here to make sure we reconnected Ethererum client correctly. 1091 // Default DNS timeout is 10 seconds. It's enough to try to reconnect only twice to cover 5 seconds lag for DNS config reload. 1092 // https://github.com/mysteriumnetwork/node/issues/2282 1093 if err := cl.Reconnect(time.Second * 15); err != nil { 1094 log.Error().Err(err).Msg("Ethereum client failed to reconnect") 1095 } 1096 } 1097 } 1098 1099 di.EventBus.Publish(registry.AppTopicEthereumClientReconnected, struct{}{}) 1100 } 1101 latestState = e.State 1102 }) 1103 } 1104 1105 func (di *Dependencies) handleNATStatusForPublicIP() { 1106 outIP, err := di.IPResolver.GetOutboundIP() 1107 if err != nil { 1108 log.Error().Err(err).Msg("Failed to get outbound IP address") 1109 } 1110 1111 pubIP, err := di.IPResolver.GetPublicIP() 1112 if err != nil { 1113 log.Error().Err(err).Msg("Failed to get public IP address") 1114 } 1115 1116 if outIP == pubIP && pubIP != "" { 1117 di.EventBus.Publish(event.AppTopicTraversal, event.BuildSuccessfulEvent("", "public_ip")) 1118 } 1119 } 1120 1121 func (di *Dependencies) bootstrapResidentCountry() error { 1122 if di.EventBus == nil { 1123 return errMissingDependency("di.EventBus") 1124 } 1125 1126 if di.LocationResolver == nil { 1127 return errMissingDependency("di.LocationResolver") 1128 } 1129 di.ResidentCountry = identity.NewResidentCountry(di.EventBus, di.LocationResolver) 1130 return nil 1131 } 1132 1133 func errMissingDependency(dep string) error { 1134 return errors.New("Missing dependency: " + dep) 1135 } 1136 1137 // AllowURLAccess allows the requested addresses to be served when the tunnel is active. 1138 func (di *Dependencies) AllowURLAccess(servers ...string) error { 1139 if _, err := firewall.AllowURLAccess(servers...); err != nil { 1140 return err 1141 } 1142 1143 if _, err := di.ServiceFirewall.AllowURLAccess(servers...); err != nil { 1144 return err 1145 } 1146 1147 return nil 1148 } 1149 1150 func getUDPListenPorts() (port.Range, error) { 1151 udpPortRange, err := port.ParseRange(config.GetString(config.FlagUDPListenPorts)) 1152 if err != nil { 1153 log.Warn().Err(err).Msg("Failed to parse UDP listen port range, using default value") 1154 return port.Range{}, fmt.Errorf("failed to parse UDP ports: %w", err) 1155 } 1156 return udpPortRange, nil 1157 } 1158 1159 func (di *Dependencies) allowTrustedDomainBypassTunnel() { 1160 allow := []string{di.NetworkDefinition.DiscoveryAddress} 1161 allow = append(allow, di.NetworkDefinition.BrokerAddresses...) 1162 1163 if err := router.ExcludeURL(allow...); err != nil { 1164 log.Error().Err(err).Msgf("Failed to exclude routes for trusted domains: %v", allow) 1165 } 1166 } 1167 1168 func (di *Dependencies) disallowTrustedDomainBypassTunnel() { 1169 allow := []string{di.NetworkDefinition.DiscoveryAddress} 1170 allow = append(allow, di.NetworkDefinition.BrokerAddresses...) 1171 1172 if err := router.RemoveExcludedURL(allow...); err != nil { 1173 log.Error().Err(err).Msgf("Failed to remove excluded routes for trusted domains: %v", allow) 1174 } 1175 } 1176 1177 func parseAddressSlice(slice []string) []common.Address { 1178 res := make([]common.Address, len(slice)) 1179 for i, s := range slice { 1180 res[i] = common.HexToAddress(s) 1181 } 1182 return res 1183 }