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  }