From 4b0daeb47b4280cefe78ef4e1a745a9fa90bc66a Mon Sep 17 00:00:00 2001 From: Andrea Maria Piana Date: Wed, 30 Jun 2021 13:40:54 +0200 Subject: [PATCH] Move services to status-node Move all the services to status-node, as some of them were there, some of them were in the geth backend and scattered around. --- account/accounts.go | 11 +- api/backend.go | 1 - api/geth_backend.go | 255 ++-------- cmd/populate-db/main.go | 34 +- cmd/populate-db/run.sh | 5 + cmd/populate-db/sync.go | 40 -- cmd/statusd/main.go | 18 +- cmd/statusd/sync.go | 40 -- common/status_node_service.go | 13 + eth-node/bridge/geth/keystore.go | 103 ++++ eth-node/bridge/geth/node.go | 52 +- eth-node/keystore/passphrase.go | 25 +- eth-node/types/key.go | 2 +- mobile/status.go | 21 - node/get_status_node.go | 311 +++--------- node/geth_node.go | 317 +----------- node/status_node_services.go | 472 ++++++++++++++++++ params/config.go | 66 +++ peers/peerpool_test.go | 11 +- protocol/messenger.go | 3 +- services/accounts/service.go | 2 +- services/appmetrics/service.go | 2 +- services/browsers/service.go | 2 +- services/ext/service.go | 13 +- services/local-notifications/core.go | 2 +- services/mailservers/service.go | 2 +- services/permissions/service.go | 2 +- services/personal/service.go | 4 +- services/rpcstats/service.go | 2 +- services/status/account_mock.go | 124 ----- services/status/api.go | 106 ---- services/status/api_test.go | 178 ------- services/status/service.go | 74 --- services/wakuext/service.go | 4 +- services/wakuv2ext/service.go | 4 +- services/wallet/service.go | 2 +- timesource/timesource.go | 2 +- .../ethereum/go-ethereum/les/client.go | 30 +- .../ethereum/go-ethereum/les/enr_entry.go | 5 - .../ethereum/go-ethereum/les/server.go | 7 +- .../ethereum/go-ethereum/p2p/dial.go | 19 +- .../ethereum/go-ethereum/p2p/discv5/README | 4 + .../go-ethereum/p2p/discv5/database.go | 25 +- .../ethereum/go-ethereum/p2p/discv5/net.go | 32 +- .../ethereum/go-ethereum/p2p/discv5/node.go | 25 - .../ethereum/go-ethereum/p2p/discv5/ntp.go | 126 ----- .../ethereum/go-ethereum/p2p/discv5/table.go | 8 +- .../ethereum/go-ethereum/p2p/discv5/ticket.go | 70 --- .../ethereum/go-ethereum/p2p/discv5/udp.go | 16 - .../ethereum/go-ethereum/p2p/server.go | 30 +- .../ethereum/go-ethereum/params/bootnodes.go | 18 - waku/waku.go | 6 +- wakuv2/waku.go | 2 +- 53 files changed, 942 insertions(+), 1806 deletions(-) create mode 100644 cmd/populate-db/run.sh create mode 100644 common/status_node_service.go create mode 100644 eth-node/bridge/geth/keystore.go create mode 100644 node/status_node_services.go delete mode 100644 services/status/account_mock.go delete mode 100644 services/status/api.go delete mode 100644 services/status/api_test.go delete mode 100644 services/status/service.go create mode 100644 vendor/github.com/ethereum/go-ethereum/p2p/discv5/README delete mode 100644 vendor/github.com/ethereum/go-ethereum/p2p/discv5/ntp.go diff --git a/account/accounts.go b/account/accounts.go index 99273aa03..cc55cd7fd 100644 --- a/account/accounts.go +++ b/account/accounts.go @@ -10,7 +10,7 @@ import ( "path/filepath" "sync" - "github.com/pborman/uuid" + "github.com/google/uuid" gethkeystore "github.com/ethereum/go-ethereum/accounts/keystore" gethcommon "github.com/ethereum/go-ethereum/common" @@ -206,12 +206,16 @@ func (m *Manager) SetAccountAddresses(main types.Address, secondary ...types.Add } // SetChatAccount initializes selectedChatAccount with privKey -func (m *Manager) SetChatAccount(privKey *ecdsa.PrivateKey) { +func (m *Manager) SetChatAccount(privKey *ecdsa.PrivateKey) error { m.mu.Lock() defer m.mu.Unlock() address := crypto.PubkeyToAddress(privKey.PublicKey) - id := uuid.NewRandom() + id, err := uuid.NewRandom() + if err != nil { + return err + } + key := &types.Key{ ID: id, Address: address, @@ -222,6 +226,7 @@ func (m *Manager) SetChatAccount(privKey *ecdsa.PrivateKey) { Address: address, AccountKey: key, } + return nil } // MainAccountAddress returns currently selected watch addresses. diff --git a/api/backend.go b/api/backend.go index ef5126f9f..3a11f04cd 100644 --- a/api/backend.go +++ b/api/backend.go @@ -35,7 +35,6 @@ type StatusBackend interface { CallPrivateRPC(inputJSON string) (string, error) CallRPC(inputJSON string) (string, error) - GetNodesFromContract(rpcEndpoint string, contractAddress string) ([]string, error) HashTransaction(sendArgs transactions.SendTxArgs) (transactions.SendTxArgs, types.Hash, error) HashTypedData(typed typeddata.TypedData) (types.Hash, error) HashTypedDataV4(typed signercore.TypedData) (types.Hash, error) diff --git a/api/geth_backend.go b/api/geth_backend.go index a3fa46e80..c2cc3c8fc 100644 --- a/api/geth_backend.go +++ b/api/geth_backend.go @@ -11,18 +11,13 @@ import ( "sync" "time" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ethcrypto "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" - gethnode "github.com/ethereum/go-ethereum/node" signercore "github.com/ethereum/go-ethereum/signer/core" "github.com/status-im/status-go/account" "github.com/status-im/status-go/appdatabase" - "github.com/status-im/status-go/appmetrics" "github.com/status-im/status-go/connection" "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/types" @@ -32,19 +27,8 @@ import ( "github.com/status-im/status-go/node" "github.com/status-im/status-go/params" "github.com/status-im/status-go/rpc" - accountssvc "github.com/status-im/status-go/services/accounts" - appmetricsservice "github.com/status-im/status-go/services/appmetrics" - "github.com/status-im/status-go/services/browsers" - localnotifications "github.com/status-im/status-go/services/local-notifications" - "github.com/status-im/status-go/services/mailservers" - "github.com/status-im/status-go/services/permissions" "github.com/status-im/status-go/services/personal" - "github.com/status-im/status-go/services/rpcfilters" - "github.com/status-im/status-go/services/rpcstats" - "github.com/status-im/status-go/services/subscriptions" "github.com/status-im/status-go/services/typeddata" - "github.com/status-im/status-go/services/wakuext" - "github.com/status-im/status-go/services/wallet" "github.com/status-im/status-go/signal" "github.com/status-im/status-go/transactions" ) @@ -58,8 +42,6 @@ var ( ErrWhisperClearIdentitiesFailure = errors.New("failed to clear whisper identities") // ErrWhisperIdentityInjectionFailure injecting whisper identities has failed. ErrWhisperIdentityInjectionFailure = errors.New("failed to inject identity into Whisper") - // ErrWakuClearIdentitiesFailure clearing whisper identities has failed. - ErrWakuClearIdentitiesFailure = errors.New("failed to clear waku identities") // ErrWakuIdentityInjectionFailure injecting whisper identities has failed. ErrWakuIdentityInjectionFailure = errors.New("failed to inject identity into waku") // ErrUnsupportedRPCMethod is for methods not supported by the RPC interface @@ -81,7 +63,6 @@ type GethStatusBackend struct { appDB *sql.DB statusNode *node.StatusNode personalAPI *personal.PublicAPI - rpcFilters *rpcfilters.Service multiaccountsDB *multiaccounts.Database account *multiaccounts.Account accountManager *account.GethManager @@ -91,6 +72,7 @@ type GethStatusBackend struct { selectedAccountKeyID string log log.Logger allowAllRPC bool // used only for tests, disables api method restrictions + } // NewGethStatusBackend create a new GethStatusBackend instance @@ -101,14 +83,12 @@ func NewGethStatusBackend() *GethStatusBackend { accountManager := account.NewGethManager() transactor := transactions.NewTransactor() personalAPI := personal.NewAPI() - rpcFilters := rpcfilters.New(statusNode) return &GethStatusBackend{ statusNode: statusNode, accountManager: accountManager, transactor: transactor, personalAPI: personalAPI, - rpcFilters: rpcFilters, log: log.New("package", "status-go/api.GethStatusBackend"), } } @@ -142,10 +122,12 @@ func (b *GethStatusBackend) IsNodeRunning() bool { func (b *GethStatusBackend) StartNode(config *params.NodeConfig) error { b.mu.Lock() defer b.mu.Unlock() + log.Info("STARTING NODE") if err := b.startNode(config); err != nil { signal.SendNodeCrashed(err) return err } + log.Info("STARTED NODE") return nil } @@ -167,6 +149,7 @@ func (b *GethStatusBackend) OpenAccounts() error { return err } b.multiaccountsDB = db + b.statusNode.SetMultiaccountsDB(db) return nil } @@ -251,6 +234,7 @@ func (b *GethStatusBackend) ensureAppDBOpened(account multiaccounts.Account, pas b.log.Error("failed to initialize db", "err", err) return err } + b.statusNode.SetAppDB(b.appDB) return nil } @@ -503,14 +487,17 @@ func (b *GethStatusBackend) StartNodeWithAccountAndConfig( nodecfg *params.NodeConfig, subaccs []accounts.Account, ) error { + log.Info("STARTING 1 NODE") err := b.SaveAccount(account) if err != nil { return err } + log.Info("STARTING 2 NODE") err = b.ensureAppDBOpened(account, password) if err != nil { return err } + log.Info("STARTING 3 NODE") err = b.saveAccountsAndSettings(settings, nodecfg, subaccs) if err != nil { return err @@ -565,66 +552,6 @@ func (b *GethStatusBackend) GetNodeConfig() (*params.NodeConfig, error) { return b.loadNodeConfig() } -func (b *GethStatusBackend) rpcFiltersService() gethnode.ServiceConstructor { - return func(*gethnode.ServiceContext) (gethnode.Service, error) { - return rpcfilters.New(b.statusNode), nil - } -} - -func (b *GethStatusBackend) subscriptionService() gethnode.ServiceConstructor { - return func(*gethnode.ServiceContext) (gethnode.Service, error) { - return subscriptions.New(func() *rpc.Client { return b.statusNode.RPCPrivateClient() }), nil - } -} - -func (b *GethStatusBackend) rpcStatsService() gethnode.ServiceConstructor { - return func(*gethnode.ServiceContext) (gethnode.Service, error) { - return rpcstats.New(), nil - } -} - -func (b *GethStatusBackend) accountsService(accountsFeed *event.Feed) gethnode.ServiceConstructor { - return func(*gethnode.ServiceContext) (gethnode.Service, error) { - return accountssvc.NewService(accounts.NewDB(b.appDB), b.multiaccountsDB, b.accountManager.Manager, accountsFeed), nil - } -} - -func (b *GethStatusBackend) browsersService() gethnode.ServiceConstructor { - return func(*gethnode.ServiceContext) (gethnode.Service, error) { - return browsers.NewService(browsers.NewDB(b.appDB)), nil - } -} - -func (b *GethStatusBackend) permissionsService() gethnode.ServiceConstructor { - return func(*gethnode.ServiceContext) (gethnode.Service, error) { - return permissions.NewService(permissions.NewDB(b.appDB)), nil - } -} - -func (b *GethStatusBackend) mailserversService() gethnode.ServiceConstructor { - return func(*gethnode.ServiceContext) (gethnode.Service, error) { - return mailservers.NewService(mailservers.NewDB(b.appDB)), nil - } -} - -func (b *GethStatusBackend) appmetricsService() gethnode.ServiceConstructor { - return func(*gethnode.ServiceContext) (gethnode.Service, error) { - return appmetricsservice.NewService(appmetrics.NewDB(b.appDB)), nil - } -} - -func (b *GethStatusBackend) walletService(network uint64, accountsFeed *event.Feed) gethnode.ServiceConstructor { - return func(*gethnode.ServiceContext) (gethnode.Service, error) { - return wallet.NewService(wallet.NewDB(b.appDB, network), accountsFeed), nil - } -} - -func (b *GethStatusBackend) localNotificationsService(network uint64) gethnode.ServiceConstructor { - return func(*gethnode.ServiceContext) (gethnode.Service, error) { - return localnotifications.NewService(b.appDB, network), nil - } -} - func (b *GethStatusBackend) startNode(config *params.NodeConfig) (err error) { defer func() { if r := recover(); r != nil { @@ -644,26 +571,12 @@ func (b *GethStatusBackend) startNode(config *params.NodeConfig) (err error) { if err := config.Validate(); err != nil { return err } - accountsFeed := &event.Feed{} - services := []gethnode.ServiceConstructor{} - services = appendIf(config.UpstreamConfig.Enabled, services, b.rpcFiltersService()) - services = append(services, b.subscriptionService()) - services = append(services, b.rpcStatsService()) - services = append(services, b.appmetricsService()) - services = appendIf(b.appDB != nil && b.multiaccountsDB != nil, services, b.accountsService(accountsFeed)) - services = appendIf(config.BrowsersConfig.Enabled, services, b.browsersService()) - services = appendIf(config.PermissionsConfig.Enabled, services, b.permissionsService()) - services = appendIf(config.MailserversConfig.Enabled, services, b.mailserversService()) - services = appendIf(config.WalletConfig.Enabled, services, b.walletService(config.NetworkID, accountsFeed)) - // We ignore for now local notifications flag as users who are upgrading have no mean to enable it - services = append(services, b.localNotificationsService(config.NetworkID)) manager := b.accountManager.GetManager() if manager == nil { return errors.New("ethereum accounts.Manager is nil") } if err = b.statusNode.StartWithOptions(config, node.StartOptions{ - Services: services, // The peers discovery protocols are started manually after // `node.ready` signal is sent. // It was discussed in https://github.com/status-im/status-go/pull/1333. @@ -672,13 +585,7 @@ func (b *GethStatusBackend) startNode(config *params.NodeConfig) (err error) { }); err != nil { return } - if config.WalletConfig.Enabled { - walletService, err := b.statusNode.WalletService() - if err != nil { - return err - } - walletService.SetClient(b.statusNode.RPCClient().Ethclient()) - } + signal.SendNodeStarted() b.transactor.SetNetworkID(config.NetworkID) @@ -691,14 +598,6 @@ func (b *GethStatusBackend) startNode(config *params.NodeConfig) (err error) { } b.log.Info("Handlers registered") - if st, err := b.statusNode.StatusService(); err == nil { - st.SetAccountManager(b.accountManager) - } - - if st, err := b.statusNode.PeerService(); err == nil { - st.SetDiscoverer(b.StatusNode()) - } - // Handle a case when a node is stopped and resumed. // If there is no account selected, an error is returned. if _, err := b.accountManager.SelectedChatAccount(); err == nil { @@ -796,7 +695,7 @@ func (b *GethStatusBackend) SendTransaction(sendArgs transactions.SendTxArgs, pa return } - go b.rpcFilters.TriggerTransactionSentToUpstreamEvent(hash) + go b.statusNode.RPCFiltersService().TriggerTransactionSentToUpstreamEvent(hash) return } @@ -807,7 +706,7 @@ func (b *GethStatusBackend) SendTransactionWithSignature(sendArgs transactions.S return } - go b.rpcFilters.TriggerTransactionSentToUpstreamEvent(hash) + go b.statusNode.RPCFiltersService().TriggerTransactionSentToUpstreamEvent(hash) return } @@ -964,10 +863,7 @@ func (b *GethStatusBackend) ConnectionChange(typ string, expensive bool) { b.log.Info("Network state change", "old", b.connectionState, "new", state) b.connectionState = state - err := b.statusNode.ConnectionChanged(state) - if err != nil { - b.log.Error("failed to notify of connection changed", "err", err) - } + b.statusNode.ConnectionChanged(state) // logic of handling state changes here // restart node? force peers reconnect? etc @@ -990,54 +886,18 @@ func (b *GethStatusBackend) AppStateChange(state string) { } func (b *GethStatusBackend) StopLocalNotifications() error { - localPN, err := b.statusNode.LocalNotificationsService() - if err != nil { - b.log.Error("Retrieving of LocalNotifications service failed on StopLocalNotifications", "error", err) + if b.statusNode == nil { return nil } - - if localPN.IsStarted() { - err = localPN.Stop() - if err != nil { - b.log.Error("LocalNotifications service stop failed on StopLocalNotifications", "error", err) - return nil - } - } - - return nil + return b.statusNode.StopLocalNotifications() } func (b *GethStatusBackend) StartLocalNotifications() error { - localPN, err := b.statusNode.LocalNotificationsService() - - if err != nil { - b.log.Error("Retrieving of local notifications service failed on StartLocalNotifications", "error", err) + if b.statusNode == nil { return nil } + return b.statusNode.StartLocalNotifications() - wallet, err := b.statusNode.WalletService() - if err != nil { - b.log.Error("Retrieving of wallet service failed on StartLocalNotifications", "error", err) - return nil - } - - if !localPN.IsStarted() { - err = localPN.Start(b.statusNode.Server()) - - if err != nil { - b.log.Error("LocalNotifications service start failed on StartLocalNotifications", "error", err) - return nil - } - } - - err = localPN.SubscribeWallet(wallet.GetFeed()) - - if err != nil { - b.log.Error("LocalNotifications service could not subscribe to wallet on StartLocalNotifications", "error", err) - return nil - } - - return nil } // Logout clears whisper identities. @@ -1061,34 +921,11 @@ func (b *GethStatusBackend) Logout() error { // cleanupServices stops parts of services that doesn't managed by a node and removes injected data from services. func (b *GethStatusBackend) cleanupServices() error { - wakuService, err := b.statusNode.WakuService() - switch err { - case node.ErrServiceUnknown: // Waku was never registered - case nil: - if err := wakuService.DeleteKeyPairs(); err != nil { - return fmt.Errorf("%s: %v", ErrWakuClearIdentitiesFailure, err) - } - b.selectedAccountKeyID = "" - default: - return err + b.selectedAccountKeyID = "" + if b.statusNode == nil { + return nil } - - if b.statusNode.Config().WalletConfig.Enabled { - wallet, err := b.statusNode.WalletService() - switch err { - case node.ErrServiceUnknown: - case nil: - if wallet.IsStarted() { - err = wallet.Stop() - if err != nil { - return err - } - } - default: - return err - } - } - return nil + return b.statusNode.Cleanup() } func (b *GethStatusBackend) closeAppDB() error { @@ -1135,9 +972,6 @@ func (b *GethStatusBackend) GetActiveAccount() (*multiaccounts.Account, error) { return b.account, nil } -func (b *GethStatusBackend) WakuExtService() (*wakuext.Service, error) { - return b.statusNode.WakuExtService() -} func (b *GethStatusBackend) injectAccountsIntoServices() error { chatAccount, err := b.accountManager.SelectedChatAccount() @@ -1152,11 +986,9 @@ func (b *GethStatusBackend) injectAccountsIntoServices() error { return err } - wakuService, err := b.statusNode.WakuService() + wakuService := b.statusNode.WakuService() - switch err { - case node.ErrServiceUnknown: // Waku was never registered - case nil: + if wakuService != nil { if err := wakuService.DeleteKeyPairs(); err != nil { // err is not possible; method return value is incorrect return err } @@ -1164,29 +996,21 @@ func (b *GethStatusBackend) injectAccountsIntoServices() error { if err != nil { return ErrWakuIdentityInjectionFailure } - default: - return err - } + st := b.statusNode.WakuExtService() - if wakuService != nil { - st, err := b.statusNode.WakuExtService() - if err != nil { - return err + if st != nil { + if err := st.InitProtocol(identity, b.appDB, b.multiaccountsDB, acc, logutils.ZapLogger()); err != nil { + return err + } + // Set initial connection state + st.ConnectionChanged(b.connectionState) } - if err := st.InitProtocol(identity, b.appDB, b.multiaccountsDB, acc, logutils.ZapLogger()); err != nil { - return err - } - - // Set initial connection state - st.ConnectionChanged(b.connectionState) } - wakuV2Service, err := b.statusNode.WakuV2Service() + wakuV2Service := b.statusNode.WakuV2Service() - switch err { - case node.ErrServiceUnknown: // WakuV2 was never registered - case nil: + if wakuV2Service != nil { if err := wakuV2Service.DeleteKeyPairs(); err != nil { // err is not possible; method return value is incorrect return err } @@ -1194,15 +1018,7 @@ func (b *GethStatusBackend) injectAccountsIntoServices() error { if err != nil { return ErrWakuIdentityInjectionFailure } - default: - return err - } - - if wakuV2Service != nil { - st, err := b.statusNode.WakuV2ExtService() - if err != nil { - return err - } + st := b.statusNode.WakuV2ExtService() if err := st.InitProtocol(identity, b.appDB, b.multiaccountsDB, acc, logutils.ZapLogger()); err != nil { return err @@ -1212,13 +1028,6 @@ func (b *GethStatusBackend) injectAccountsIntoServices() error { return nil } -func appendIf(condition bool, services []gethnode.ServiceConstructor, service gethnode.ServiceConstructor) []gethnode.ServiceConstructor { - if !condition { - return services - } - return append(services, service) -} - // ExtractGroupMembershipSignatures extract signatures from tuples of content/signature func (b *GethStatusBackend) ExtractGroupMembershipSignatures(signaturePairs [][2]string) ([]string, error) { return crypto.ExtractSignatures(signaturePairs) diff --git a/cmd/populate-db/main.go b/cmd/populate-db/main.go index efd08f5a0..45b161228 100644 --- a/cmd/populate-db/main.go +++ b/cmd/populate-db/main.go @@ -140,13 +140,13 @@ func main() { backend := api.NewGethStatusBackend() err = ImportAccount(*seedPhrase, backend) if err != nil { - logger.Error("failed", "err", err) + logger.Error("failed import account", "err", err) return } - wakuextservice, err := backend.WakuExtService() - if err != nil { - logger.Error("failed", "err", err) + wakuextservice := backend.StatusNode().WakuExtService() + if wakuextservice == nil { + logger.Error("wakuext not available") return } @@ -165,14 +165,14 @@ func main() { for i := 0; i < *nAddedContacts; i++ { key, err := crypto.GenerateKey() if err != nil { - logger.Error("failed", err) + logger.Error("failed generate key", err) return } keyString := common.PubkeyToHex(&key.PublicKey) _, err = wakuext.AddContact(context.Background(), keyString) if err != nil { - logger.Error("failed", "err", err) + logger.Error("failed Add contact", "err", err) return } } @@ -253,6 +253,11 @@ func main() { } } + url := "enode://30211cbd81c25f07b03a0196d56e6ce4604bb13db773ff1c0ea2253547fafd6c06eae6ad3533e2ba39d59564cfbdbb5e2ce7c137a5ebb85e99dcfc7a75f99f55@23.236.58.92:443" + fmt.Println("UPDATING") + wakuext.UpdateMailservers([]string{url}) + time.Sleep(10 * time.Second) + fmt.Println("UPDATED") } @@ -427,21 +432,25 @@ func ImportAccount(seedPhrase string, backend *api.GethStatusBackend) error { manager.InitKeystore("./tmp") err := backend.OpenAccounts() if err != nil { + logger.Error("failed open accounts", err) return err } generator := manager.AccountsGenerator() generatedAccountInfo, err := generator.ImportMnemonic(seedPhrase, "") if err != nil { + logger.Error("import mnemonic", err) return err } derivedAddresses, err := generator.DeriveAddresses(generatedAccountInfo.ID, paths) if err != nil { + logger.Error("deriver addressess", err) return err } _, err = generator.StoreDerivedAccounts(generatedAccountInfo.ID, "", paths) if err != nil { + logger.Error("store addressess", err) return err } @@ -450,11 +459,13 @@ func ImportAccount(seedPhrase string, backend *api.GethStatusBackend) error { } settings, err := defaultSettings(generatedAccountInfo, derivedAddresses, &seedPhrase) if err != nil { + logger.Error("default settings", err) return err } nodeConfig, err := defaultNodeConfig(settings.InstallationID) if err != nil { + logger.Error("node config", err) return err } @@ -477,8 +488,15 @@ func ImportAccount(seedPhrase string, backend *api.GethStatusBackend) error { Path: pathDefaultChat, } + fmt.Println(nodeConfig) accounts := []accounts.Account{walletAccount, chatAccount} - return backend.StartNodeWithAccountAndConfig(account, "", *settings, nodeConfig, accounts) + err = backend.StartNodeWithAccountAndConfig(account, "", *settings, nodeConfig, accounts) + if err != nil { + logger.Error("start node", err) + return err + } + + return nil } var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") @@ -486,7 +504,7 @@ var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") func buildMessage(chat *protocol.Chat, count int) *common.Message { key, err := crypto.GenerateKey() if err != nil { - logger.Error("failed", err) + logger.Error("failed build message", err) return nil } diff --git a/cmd/populate-db/run.sh b/cmd/populate-db/run.sh new file mode 100644 index 000000000..82e4abd1b --- /dev/null +++ b/cmd/populate-db/run.sh @@ -0,0 +1,5 @@ + +#/bin/bash +go build -mod=vendor +rm ./tmp -rf +./populate-db --added-contacts 1 --contacts 2 --public-chats 1 --one-to-one-chats 4 --number-of-messages 2 --seed-phrase "wolf uncover ancient kiss deer blossom blind expose estate average cancel kiss" diff --git a/cmd/populate-db/sync.go b/cmd/populate-db/sync.go index 18658a3c8..f555b7a70 100644 --- a/cmd/populate-db/sync.go +++ b/cmd/populate-db/sync.go @@ -3,8 +3,6 @@ package main import ( "context" "time" - - "github.com/status-im/status-go/node" ) func createContextFromTimeout(timeout int) (context.Context, context.CancelFunc) { @@ -14,41 +12,3 @@ func createContextFromTimeout(timeout int) (context.Context, context.CancelFunc) return context.WithTimeout(context.Background(), time.Duration(timeout)*time.Minute) } - -// syncAndStopNode tries to sync the blockchain and stop the node. -// It returns an exit code (`0` if successful or `1` in case of error) -// that can be used in `os.Exit` to exit immediately when the function returns. -// The special exit code `-1` is used if execution was interrupted. -func syncAndStopNode(interruptCh <-chan struct{}, statusNode *node.StatusNode, timeout int) (exitCode int) { - - logger.Info("syncAndStopNode: node will synchronize the chain and exit", "timeoutInMins", timeout) - - ctx, cancel := createContextFromTimeout(timeout) - defer cancel() - - doneSync := make(chan struct{}) - errSync := make(chan error) - go func() { - if err := statusNode.EnsureSync(ctx); err != nil { - errSync <- err - } - close(doneSync) - }() - - select { - case err := <-errSync: - logger.Error("syncAndStopNode: failed to sync the chain", "error", err) - exitCode = 1 - case <-doneSync: - case <-interruptCh: - // cancel context and return immediately if interrupted - // `-1` is used as a special exit code to denote interruption - return -1 - } - - if err := statusNode.Stop(); err != nil { - logger.Error("syncAndStopNode: failed to stop the node", "error", err) - return 1 - } - return -} diff --git a/cmd/statusd/main.go b/cmd/statusd/main.go index fb9f817a5..5246569bc 100644 --- a/cmd/statusd/main.go +++ b/cmd/statusd/main.go @@ -71,8 +71,6 @@ var ( // don't change the name of this flag, https://github.com/ethereum/go-ethereum/blob/master/metrics/metrics.go#L41 metricsEnabled = flag.Bool("metrics", false, "Expose ethereum metrics with debug_metrics jsonrpc call") metricsPort = flag.Int("metrics-port", 9305, "Port for the Prometheus /metrics endpoint") - - syncAndExit = flag.Int("sync-and-exit", -1, "Timeout in minutes for blockchain sync and exit, zero means no timeout unless sync is finished") ) // All general log messages in this package should be routed through this logger. @@ -182,20 +180,6 @@ func main() { profiling.NewProfiler(*pprofPort).Go() } - // Sync blockchain and stop. - if *syncAndExit >= 0 { - exitCode := syncAndStopNode(interruptCh, backend.StatusNode(), *syncAndExit) - // Call was interrupted. Wait for graceful shutdown. - if exitCode == -1 { - if gethNode := backend.StatusNode().GethNode(); gethNode != nil { - gethNode.Wait() - } - return - } - // Otherwise, exit immediately with a returned exit code. - os.Exit(exitCode) - } - if config.PushNotificationServerConfig.Enabled { if config.NodeKey == "" { logger.Error("node key needs to be set if running a push notification server") @@ -227,7 +211,7 @@ func main() { protocol.WithDatabase(db), } - messenger, err := protocol.NewMessenger(identity, gethbridge.NewNodeBridge(backend.StatusNode().GethNode()), installationID.String(), options...) + messenger, err := protocol.NewMessenger(identity, gethbridge.NewNodeBridge(backend.StatusNode().GethNode(), backend.StatusNode().WakuService(), backend.StatusNode().WakuV2Service()), installationID.String(), options...) if err != nil { logger.Error("failed to create messenger", "error", err) return diff --git a/cmd/statusd/sync.go b/cmd/statusd/sync.go index 18658a3c8..f555b7a70 100644 --- a/cmd/statusd/sync.go +++ b/cmd/statusd/sync.go @@ -3,8 +3,6 @@ package main import ( "context" "time" - - "github.com/status-im/status-go/node" ) func createContextFromTimeout(timeout int) (context.Context, context.CancelFunc) { @@ -14,41 +12,3 @@ func createContextFromTimeout(timeout int) (context.Context, context.CancelFunc) return context.WithTimeout(context.Background(), time.Duration(timeout)*time.Minute) } - -// syncAndStopNode tries to sync the blockchain and stop the node. -// It returns an exit code (`0` if successful or `1` in case of error) -// that can be used in `os.Exit` to exit immediately when the function returns. -// The special exit code `-1` is used if execution was interrupted. -func syncAndStopNode(interruptCh <-chan struct{}, statusNode *node.StatusNode, timeout int) (exitCode int) { - - logger.Info("syncAndStopNode: node will synchronize the chain and exit", "timeoutInMins", timeout) - - ctx, cancel := createContextFromTimeout(timeout) - defer cancel() - - doneSync := make(chan struct{}) - errSync := make(chan error) - go func() { - if err := statusNode.EnsureSync(ctx); err != nil { - errSync <- err - } - close(doneSync) - }() - - select { - case err := <-errSync: - logger.Error("syncAndStopNode: failed to sync the chain", "error", err) - exitCode = 1 - case <-doneSync: - case <-interruptCh: - // cancel context and return immediately if interrupted - // `-1` is used as a special exit code to denote interruption - return -1 - } - - if err := statusNode.Stop(); err != nil { - logger.Error("syncAndStopNode: failed to stop the node", "error", err) - return 1 - } - return -} diff --git a/common/status_node_service.go b/common/status_node_service.go new file mode 100644 index 000000000..d457c6b7c --- /dev/null +++ b/common/status_node_service.go @@ -0,0 +1,13 @@ +package common + +import ( + "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/rpc" +) + +type StatusService interface { + Start() error + Stop() error + Protocols() []p2p.Protocol + APIs() []rpc.API +} diff --git a/eth-node/bridge/geth/keystore.go b/eth-node/bridge/geth/keystore.go new file mode 100644 index 000000000..a71a5541b --- /dev/null +++ b/eth-node/bridge/geth/keystore.go @@ -0,0 +1,103 @@ +package gethbridge + +import ( + "crypto/ecdsa" + "errors" + "strings" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" + + "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/extkeys" +) + +type gethKeyStoreAdapter struct { + keystore *keystore.KeyStore +} + +// WrapKeyStore creates a types.KeyStore wrapper over a keystore.KeyStore object +func WrapKeyStore(keystore *keystore.KeyStore) types.KeyStore { + return &gethKeyStoreAdapter{keystore: keystore} +} + +func (k *gethKeyStoreAdapter) ImportECDSA(priv *ecdsa.PrivateKey, passphrase string) (types.Account, error) { + gethAccount, err := k.keystore.ImportECDSA(priv, passphrase) + return accountFrom(gethAccount), err +} + +func (k *gethKeyStoreAdapter) ImportSingleExtendedKey(extKey *extkeys.ExtendedKey, passphrase string) (types.Account, error) { + gethAccount, err := k.keystore.ImportSingleExtendedKey(extKey, passphrase) + return accountFrom(gethAccount), err +} + +func (k *gethKeyStoreAdapter) ImportExtendedKeyForPurpose(keyPurpose extkeys.KeyPurpose, extKey *extkeys.ExtendedKey, passphrase string) (types.Account, error) { + gethAccount, err := k.keystore.ImportExtendedKeyForPurpose(keyPurpose, extKey, passphrase) + return accountFrom(gethAccount), err +} + +func (k *gethKeyStoreAdapter) AccountDecryptedKey(a types.Account, auth string) (types.Account, *types.Key, error) { + gethAccount, err := gethAccountFrom(a) + if err != nil { + return types.Account{}, nil, err + } + + var gethKey *keystore.Key + gethAccount, gethKey, err = k.keystore.AccountDecryptedKey(gethAccount, auth) + return accountFrom(gethAccount), keyFrom(gethKey), err +} + +func (k *gethKeyStoreAdapter) Delete(a types.Account, auth string) error { + gethAccount, err := gethAccountFrom(a) + if err != nil { + return err + } + + return k.keystore.Delete(gethAccount, auth) +} + +// parseGethURL converts a user supplied URL into the accounts specific structure. +func parseGethURL(url string) (accounts.URL, error) { + parts := strings.Split(url, "://") + if len(parts) != 2 || parts[0] == "" { + return accounts.URL{}, errors.New("protocol scheme missing") + } + return accounts.URL{ + Scheme: parts[0], + Path: parts[1], + }, nil +} + +func gethAccountFrom(account types.Account) (accounts.Account, error) { + var ( + gethAccount accounts.Account + err error + ) + gethAccount.Address = common.Address(account.Address) + if account.URL != "" { + gethAccount.URL, err = parseGethURL(account.URL) + } + return gethAccount, err +} + +func accountFrom(gethAccount accounts.Account) types.Account { + return types.Account{ + Address: types.Address(gethAccount.Address), + URL: gethAccount.URL.String(), + } +} + +func keyFrom(k *keystore.Key) *types.Key { + if k == nil { + return nil + } + + return &types.Key{ + ID: k.Id, + Address: types.Address(k.Address), + PrivateKey: k.PrivateKey, + ExtendedKey: k.ExtendedKey, + SubAccountIndex: k.SubAccountIndex, + } +} diff --git a/eth-node/bridge/geth/node.go b/eth-node/bridge/geth/node.go index 1cb9d098c..91088080a 100644 --- a/eth-node/bridge/geth/node.go +++ b/eth-node/bridge/geth/node.go @@ -18,10 +18,12 @@ import ( type gethNodeWrapper struct { stack *node.Node + waku1 *waku.Waku + waku2 *wakuv2.Waku } -func NewNodeBridge(stack *node.Node) types.Node { - return &gethNodeWrapper{stack: stack} +func NewNodeBridge(stack *node.Node, waku1 *waku.Waku, waku2 *wakuv2.Waku) types.Node { + return &gethNodeWrapper{stack: stack, waku1: waku1, waku2: waku2} } func (w *gethNodeWrapper) Poll() { @@ -32,50 +34,28 @@ func (w *gethNodeWrapper) NewENSVerifier(logger *zap.Logger) enstypes.ENSVerifie return gethens.NewVerifier(logger) } +func (w *gethNodeWrapper) SetWaku1(waku *waku.Waku) { + w.waku1 = waku +} + +func (w *gethNodeWrapper) SetWaku2(waku *wakuv2.Waku) { + w.waku2 = waku +} + func (w *gethNodeWrapper) GetWaku(ctx interface{}) (types.Waku, error) { - var nativeWaku *waku.Waku - if ctx == nil || ctx == w { - err := w.stack.Service(&nativeWaku) - if err != nil { - return nil, err - } - } else { - switch serviceProvider := ctx.(type) { - case *node.ServiceContext: - err := serviceProvider.Service(&nativeWaku) - if err != nil { - return nil, err - } - } - } - if nativeWaku == nil { + if w.waku1 == nil { return nil, errors.New("waku service is not available") } - return NewGethWakuWrapper(nativeWaku), nil + return NewGethWakuWrapper(w.waku1), nil } func (w *gethNodeWrapper) GetWakuV2(ctx interface{}) (types.Waku, error) { - var nativeWaku *wakuv2.Waku - if ctx == nil || ctx == w { - err := w.stack.Service(&nativeWaku) - if err != nil { - return nil, err - } - } else { - switch serviceProvider := ctx.(type) { - case *node.ServiceContext: - err := serviceProvider.Service(&nativeWaku) - if err != nil { - return nil, err - } - } - } - if nativeWaku == nil { + if w.waku2 == nil { return nil, errors.New("waku service is not available") } - return NewGethWakuV2Wrapper(nativeWaku), nil + return NewGethWakuV2Wrapper(w.waku2), nil } func (w *gethNodeWrapper) AddPeer(url string) error { diff --git a/eth-node/keystore/passphrase.go b/eth-node/keystore/passphrase.go index c7c331e0a..cfb47ea39 100644 --- a/eth-node/keystore/passphrase.go +++ b/eth-node/keystore/passphrase.go @@ -12,7 +12,7 @@ import ( "encoding/json" "fmt" - "github.com/pborman/uuid" + "github.com/google/uuid" "golang.org/x/crypto/pbkdf2" "golang.org/x/crypto/scrypt" @@ -107,8 +107,13 @@ func DecryptKey(keyjson []byte, auth string) (*types.Key, error) { } key := crypto.ToECDSAUnsafe(keyBytes) + id, err := uuid.FromBytes(keyId) + if err != nil { + return nil, err + } + return &types.Key{ - ID: uuid.UUID(keyId), + ID: id, Address: crypto.PubkeyToAddress(key.PublicKey), PrivateKey: key, ExtendedKey: extKey, @@ -156,7 +161,11 @@ func decryptKeyV3(keyProtected *encryptedKeyJSONV3, auth string) (keyBytes []byt if keyProtected.Version != version { return nil, nil, fmt.Errorf("Version not supported: %v", keyProtected.Version) } - keyId = uuid.Parse(keyProtected.Id) + id, err := uuid.Parse(keyProtected.Id) + if err != nil { + return nil, nil, err + } + keyId = id[:] plainText, err := DecryptDataV3(keyProtected.Crypto, auth) if err != nil { return nil, nil, err @@ -165,7 +174,12 @@ func decryptKeyV3(keyProtected *encryptedKeyJSONV3, auth string) (keyBytes []byt } func decryptKeyV1(keyProtected *encryptedKeyJSONV1, auth string) (keyBytes []byte, keyId []byte, err error) { - keyId = uuid.Parse(keyProtected.Id) + id, err := uuid.Parse(keyProtected.Id) + if err != nil { + return nil, nil, err + } + keyId = id[:] + mac, err := hex.DecodeString(keyProtected.Crypto.MAC) if err != nil { return nil, nil, err @@ -329,8 +343,7 @@ func pkcs7Unpad(in []byte) []byte { return in[:len(in)-int(padding)] } - -func RawKeyToCryptoJSON(rawKeyFile []byte) (cj CryptoJSON, e error){ +func RawKeyToCryptoJSON(rawKeyFile []byte) (cj CryptoJSON, e error) { var keyJSON encryptedKeyJSONV3 if e := json.Unmarshal(rawKeyFile, &keyJSON); e != nil { return cj, fmt.Errorf("failed to read key file: %s", e) diff --git a/eth-node/types/key.go b/eth-node/types/key.go index 1b2804677..b74b16a8c 100644 --- a/eth-node/types/key.go +++ b/eth-node/types/key.go @@ -3,7 +3,7 @@ package types import ( "crypto/ecdsa" - "github.com/pborman/uuid" + "github.com/google/uuid" "github.com/status-im/status-go/extkeys" ) diff --git a/mobile/status.go b/mobile/status.go index 571c3792d..f560c87c8 100644 --- a/mobile/status.go +++ b/mobile/status.go @@ -516,27 +516,6 @@ func makeJSONResponse(err error) string { return string(outBytes) } -// GetNodesFromContract returns a list of nodes from a given contract -//export GetNodesFromContract -func GetNodesFromContract(rpcEndpoint string, contractAddress string) string { - nodes, err := statusBackend.GetNodesFromContract( - rpcEndpoint, - contractAddress, - ) - if err != nil { - return makeJSONResponse(err) - } - - data, err := json.Marshal(struct { - Nodes []string `json:"result"` - }{Nodes: nodes}) - if err != nil { - return makeJSONResponse(err) - } - - return string(data) -} - // AddPeer adds an enode as a peer. func AddPeer(enode string) string { err := statusBackend.StatusNode().AddPeer(enode) diff --git a/node/get_status_node.go b/node/get_status_node.go index 4fa76bccd..d54af163e 100644 --- a/node/get_status_node.go +++ b/node/get_status_node.go @@ -1,7 +1,7 @@ package node import ( - "context" + "database/sql" "errors" "fmt" "net" @@ -16,27 +16,36 @@ import ( "github.com/syndtr/goleveldb/leveldb" "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/les" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" + "github.com/status-im/status-go/account" "github.com/status-im/status-go/connection" "github.com/status-im/status-go/db" "github.com/status-im/status-go/discovery" + "github.com/status-im/status-go/multiaccounts" "github.com/status-im/status-go/params" "github.com/status-im/status-go/peers" "github.com/status-im/status-go/rpc" + accountssvc "github.com/status-im/status-go/services/accounts" + appmetricsservice "github.com/status-im/status-go/services/appmetrics" "github.com/status-im/status-go/services/browsers" localnotifications "github.com/status-im/status-go/services/local-notifications" + "github.com/status-im/status-go/services/mailservers" + "github.com/status-im/status-go/services/nodebridge" "github.com/status-im/status-go/services/peer" "github.com/status-im/status-go/services/permissions" - "github.com/status-im/status-go/services/status" + "github.com/status-im/status-go/services/personal" + "github.com/status-im/status-go/services/rpcfilters" + "github.com/status-im/status-go/services/rpcstats" + "github.com/status-im/status-go/services/subscriptions" "github.com/status-im/status-go/services/wakuext" "github.com/status-im/status-go/services/wakuv2ext" "github.com/status-im/status-go/services/wallet" + "github.com/status-im/status-go/timesource" "github.com/status-im/status-go/waku" "github.com/status-im/status-go/wakuv2" ) @@ -59,6 +68,9 @@ var ( type StatusNode struct { mu sync.RWMutex + appDB *sql.DB + multiaccountsDB *multiaccounts.Database + config *params.NodeConfig // Status node configuration gethNode *node.Node // reference to Geth P2P stack/node rpcClient *rpc.Client // reference to public RPC client @@ -70,12 +82,37 @@ type StatusNode struct { db *leveldb.DB // used as a cache for PeerPool log log.Logger + + gethAccountManager *account.GethManager + accountsManager *accounts.Manager + + // services + // Not sure whether we can use the one that has already be initalized above + rpcFiltersSrvc *rpcfilters.Service + subscriptionsSrvc *subscriptions.Service + rpcStatsSrvc *rpcstats.Service + accountsSrvc *accountssvc.Service + browsersSrvc *browsers.Service + nodeBridgeSrvc *nodebridge.NodeService + permissionsSrvc *permissions.Service + mailserversSrvc *mailservers.Service + appMetricsSrvc *appmetricsservice.Service + walletSrvc *wallet.Service + peerSrvc *peer.Service + localNotificationsSrvc *localnotifications.Service + personalSrvc *personal.Service + timeSourceSrvc *timesource.NTPTimeSource + wakuSrvc *waku.Waku + wakuExtSrvc *wakuext.Service + wakuV2Srvc *wakuv2.Waku + wakuV2ExtSrvc *wakuv2ext.Service } // New makes new instance of StatusNode. func New() *StatusNode { return &StatusNode{ - log: log.New("package", "status-go/node.StatusNode"), + gethAccountManager: account.NewGethManager(), + log: log.New("package", "status-go/node.StatusNode"), } } @@ -109,9 +146,9 @@ func (n *StatusNode) Server() *p2p.Server { // Start starts current StatusNode, failing if it's already started. // It accepts a list of services that should be added to the node. -func (n *StatusNode) Start(config *params.NodeConfig, accs *accounts.Manager, services ...node.ServiceConstructor) error { +func (n *StatusNode) Start(config *params.NodeConfig, accs *accounts.Manager) error { + n.accountsManager = accs return n.StartWithOptions(config, StartOptions{ - Services: services, StartDiscovery: true, AccountsManager: accs, }) @@ -119,7 +156,6 @@ func (n *StatusNode) Start(config *params.NodeConfig, accs *accounts.Manager, se // StartOptions allows to control some parameters of Start() method. type StartOptions struct { - Services []node.ServiceConstructor StartDiscovery bool AccountsManager *accounts.Manager } @@ -135,6 +171,8 @@ func (n *StatusNode) StartWithOptions(config *params.NodeConfig, options StartOp return ErrNodeRunning } + n.accountsManager = options.AccountsManager + n.log.Debug("starting with options", "ClusterConfig", config.ClusterConfig) db, err := db.Create(config.DataDir, params.StatusDatabase) @@ -143,9 +181,11 @@ func (n *StatusNode) StartWithOptions(config *params.NodeConfig, options StartOp } n.db = db + n.log.Info("starting with db") - err = n.startWithDB(config, options.AccountsManager, db, options.Services) + err = n.startWithDB(config, options.AccountsManager, db) + n.log.Info("started with db") // continue only if there was no error when starting node with a db if err == nil && options.StartDiscovery && n.discoveryEnabled() { err = n.startDiscovery() @@ -162,21 +202,22 @@ func (n *StatusNode) StartWithOptions(config *params.NodeConfig, options StartOp return nil } -func (n *StatusNode) startWithDB(config *params.NodeConfig, accs *accounts.Manager, db *leveldb.DB, services []node.ServiceConstructor) error { +func (n *StatusNode) startWithDB(config *params.NodeConfig, accs *accounts.Manager, db *leveldb.DB) error { if err := n.createNode(config, accs, db); err != nil { return err } n.config = config + n.log.Info("starting geth node") - if err := n.startGethNode(services); err != nil { - return err - } - + n.log.Info("setting up rpc client") if err := n.setupRPCClient(); err != nil { return err } - return nil + if err := n.initServices(config); err != nil { + return err + } + return n.startGethNode() } func (n *StatusNode) createNode(config *params.NodeConfig, accs *accounts.Manager, db *leveldb.DB) (err error) { @@ -185,19 +226,13 @@ func (n *StatusNode) createNode(config *params.NodeConfig, accs *accounts.Manage } // startGethNode starts current StatusNode, will fail if it's already started. -func (n *StatusNode) startGethNode(services []node.ServiceConstructor) error { - for _, service := range services { - if err := n.gethNode.Register(service); err != nil { - return err - } - } - +func (n *StatusNode) startGethNode() error { return n.gethNode.Start() } func (n *StatusNode) setupRPCClient() (err error) { // setup public RPC client - gethNodeClient, err := n.gethNode.AttachPublic() + gethNodeClient, err := n.gethNode.Attach() if err != nil { return } @@ -315,8 +350,6 @@ func (n *StatusNode) startDiscovery() error { options.AllowStop = len(n.config.RegisterTopics) == 0 options.TrustedMailServers = parseNodesToNodeID(n.config.ClusterConfig.TrustedMailServers) - options.MailServerRegistryAddress = n.config.MailServerRegistryAddress - n.peerPool = peers.NewPeerPool( n.discovery, n.config.RequireTopics, @@ -355,7 +388,7 @@ func (n *StatusNode) stop() error { n.discovery = nil } - if err := n.gethNode.Stop(); err != nil { + if err := n.gethNode.Close(); err != nil { return err } @@ -520,163 +553,12 @@ func (n *StatusNode) PeerCount() int { return n.gethNode.Server().PeerCount() } -// gethService is a wrapper for gethNode.Service which retrieves a currently -// running service registered of a specific type. -func (n *StatusNode) gethService(serviceInstance interface{}) error { - if !n.isRunning() { - return ErrNoRunningNode +func (n *StatusNode) ConnectionChanged(state connection.State) { + if n.wakuExtSrvc == nil { + return } - if err := n.gethNode.Service(serviceInstance); err != nil { - return err - } - - return nil -} - -// LightEthereumService exposes reference to LES service running on top of the node -func (n *StatusNode) LightEthereumService() (l *les.LightEthereum, err error) { - n.mu.RLock() - defer n.mu.RUnlock() - - err = n.gethService(&l) - if err == node.ErrServiceUnknown { - err = ErrServiceUnknown - } - - return -} - -// StatusService exposes reference to status service running on top of the node -func (n *StatusNode) StatusService() (st *status.Service, err error) { - n.mu.RLock() - defer n.mu.RUnlock() - - err = n.gethService(&st) - if err == node.ErrServiceUnknown { - err = ErrServiceUnknown - } - - return -} - -// PeerService exposes reference to peer service running on top of the node. -func (n *StatusNode) PeerService() (st *peer.Service, err error) { - n.mu.RLock() - defer n.mu.RUnlock() - - err = n.gethService(&st) - if err == node.ErrServiceUnknown { - err = ErrServiceUnknown - } - - return -} - -// WakuService exposes reference to Waku service running on top of the node -func (n *StatusNode) WakuService() (w *waku.Waku, err error) { - n.mu.RLock() - defer n.mu.RUnlock() - - err = n.gethService(&w) - if err == node.ErrServiceUnknown { - err = ErrServiceUnknown - } - - return -} - -// WakuV2Service exposes reference to Whisper service running on top of the node -func (n *StatusNode) WakuV2Service() (w *wakuv2.Waku, err error) { - n.mu.RLock() - defer n.mu.RUnlock() - - err = n.gethService(&w) - if err == node.ErrServiceUnknown { - err = ErrServiceUnknown - } - - return -} - -// WakuExtService exposes reference to shh extension service running on top of the node -func (n *StatusNode) WakuExtService() (s *wakuext.Service, err error) { - n.mu.RLock() - defer n.mu.RUnlock() - - err = n.gethService(&s) - if err == node.ErrServiceUnknown { - err = ErrServiceUnknown - } - - return -} - -func (n *StatusNode) ConnectionChanged(state connection.State) error { - service, err := n.WakuExtService() - if err != nil { - return err - } - - service.ConnectionChanged(state) - return nil -} - -// WakuV2ExtService exposes reference to waku v2 extension service running on top of the node -func (n *StatusNode) WakuV2ExtService() (s *wakuv2ext.Service, err error) { - n.mu.RLock() - defer n.mu.RUnlock() - - err = n.gethService(&s) - if err == node.ErrServiceUnknown { - err = ErrServiceUnknown - } - - return -} - -// WalletService returns wallet.Service instance if it was started. -func (n *StatusNode) WalletService() (s *wallet.Service, err error) { - n.mu.RLock() - defer n.mu.RUnlock() - err = n.gethService(&s) - if err == node.ErrServiceUnknown { - err = ErrServiceUnknown - } - return -} - -// LocalNotificationsService returns localnotifications.Service instance if it was started. -func (n *StatusNode) LocalNotificationsService() (s *localnotifications.Service, err error) { - n.mu.RLock() - defer n.mu.RUnlock() - err = n.gethService(&s) - if err == node.ErrServiceUnknown { - err = ErrServiceUnknown - } - return -} - -// BrowsersService returns browsers.Service instance if it was started. -func (n *StatusNode) BrowsersService() (s *browsers.Service, err error) { - n.mu.RLock() - defer n.mu.RUnlock() - err = n.gethService(&s) - if err == node.ErrServiceUnknown { - err = ErrServiceUnknown - } - return -} - -// PermissionsService returns browsers.Service instance if it was started. -func (n *StatusNode) PermissionsService() (s *permissions.Service, err error) { - n.mu.RLock() - defer n.mu.RUnlock() - err = n.gethService(&s) - if err == node.ErrServiceUnknown { - err = ErrServiceUnknown - } - return + n.wakuExtSrvc.ConnectionChanged(state) } // AccountManager exposes reference to node's accounts manager @@ -735,67 +617,6 @@ func (n *StatusNode) ChaosModeCheckRPCClientsUpstreamURL(on bool) error { return nil } -// EnsureSync waits until blockchain synchronization -// is complete and returns. -func (n *StatusNode) EnsureSync(ctx context.Context) error { - // Don't wait for any blockchain sync for the - // local private chain as blocks are never mined. - if n.config.NetworkID == 0 || n.config.NetworkID == params.StatusChainNetworkID { - return nil - } - - return n.ensureSync(ctx) -} - -func (n *StatusNode) ensureSync(ctx context.Context) error { - les, err := n.LightEthereumService() - if err != nil { - return fmt.Errorf("failed to get LES service: %v", err) - } - - downloader := les.Downloader() - if downloader == nil { - return errors.New("LightEthereumService downloader is nil") - } - - progress := downloader.Progress() - if n.PeerCount() > 0 && progress.CurrentBlock >= progress.HighestBlock { - n.log.Debug("Synchronization completed", "current block", progress.CurrentBlock, "highest block", progress.HighestBlock) - return nil - } - - ticker := time.NewTicker(tickerResolution) - defer ticker.Stop() - - progressTicker := time.NewTicker(time.Minute) - defer progressTicker.Stop() - - for { - select { - case <-ctx.Done(): - return errors.New("timeout during node synchronization") - case <-ticker.C: - if n.PeerCount() == 0 { - n.log.Debug("No established connections with any peers, continue waiting for a sync") - continue - } - if downloader.Synchronising() { - n.log.Debug("Synchronization is in progress") - continue - } - progress = downloader.Progress() - if progress.CurrentBlock >= progress.HighestBlock { - n.log.Info("Synchronization completed", "current block", progress.CurrentBlock, "highest block", progress.HighestBlock) - return nil - } - n.log.Debug("Synchronization is not finished", "current", progress.CurrentBlock, "highest", progress.HighestBlock) - case <-progressTicker.C: - progress = downloader.Progress() - n.log.Warn("Synchronization is not finished", "current", progress.CurrentBlock, "highest", progress.HighestBlock) - } - } -} - // Discover sets up the discovery for a specific topic. func (n *StatusNode) Discover(topic string, max, min int) (err error) { if n.peerPool == nil { @@ -806,3 +627,11 @@ func (n *StatusNode) Discover(topic string, max, min int) (err error) { Min: min, }) } + +func (n *StatusNode) SetAppDB(db *sql.DB) { + n.appDB = db +} + +func (n *StatusNode) SetMultiaccountsDB(db *multiaccounts.Database) { + n.multiaccountsDB = db +} diff --git a/node/geth_node.go b/node/geth_node.go index 5345105e0..bfa7b8a88 100644 --- a/node/geth_node.go +++ b/node/geth_node.go @@ -6,17 +6,11 @@ import ( "fmt" "os" "path/filepath" - "time" - - logging "github.com/ipfs/go-log" "github.com/syndtr/goleveldb/leveldb" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/les" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p" @@ -24,22 +18,9 @@ import ( "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/nat" - gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" "github.com/status-im/status-go/eth-node/crypto" - "github.com/status-im/status-go/logutils" - "github.com/status-im/status-go/mailserver" "github.com/status-im/status-go/params" - "github.com/status-im/status-go/services/ext" - "github.com/status-im/status-go/services/nodebridge" - "github.com/status-im/status-go/services/peer" - "github.com/status-im/status-go/services/personal" - "github.com/status-im/status-go/services/wakuext" - "github.com/status-im/status-go/services/wakuv2ext" "github.com/status-im/status-go/static" - "github.com/status-im/status-go/timesource" - "github.com/status-im/status-go/waku" - wakucommon "github.com/status-im/status-go/waku/common" - "github.com/status-im/status-go/wakuv2" ) // Errors related to node and services creation. @@ -83,77 +64,9 @@ func MakeNode(config *params.NodeConfig, accs *accounts.Manager, db *leveldb.DB) return nil, fmt.Errorf(ErrNodeMakeFailureFormat, err.Error()) } - err = activateServices(stack, config, accs, db) - if err != nil { - return nil, err - } return stack, nil } -func activateServices(stack *node.Node, config *params.NodeConfig, accs *accounts.Manager, db *leveldb.DB) error { - if config.EnableNTPSync { - err := stack.Register(func(*node.ServiceContext) (node.Service, error) { - return timesource.Default(), nil - }) - if err != nil { - return fmt.Errorf("failed to register NTP time source: %v", err) - } - } - - // start Ethereum service if we are not expected to use an upstream server - if !config.UpstreamConfig.Enabled { - if err := activateLightEthService(stack, accs, config); err != nil { - return fmt.Errorf("%v: %v", ErrLightEthRegistrationFailure, err) - } - } else { - if config.LightEthConfig.Enabled { - return ErrLightEthRegistrationFailureUpstreamEnabled - } - - logger.Info("LES protocol is disabled") - - // `personal_sign` and `personal_ecRecover` methods are important to - // keep DApps working. - // Usually, they are provided by an ETH or a LES service, but when using - // upstream, we don't start any of these, so we need to start our own - // implementation. - if err := activatePersonalService(stack, accs, config); err != nil { - return fmt.Errorf("%v: %v", ErrPersonalServiceRegistrationFailure, err) - } - } - - if err := activateNodeServices(stack, config, db); err != nil { - return err - } - - return nil -} - -func activateNodeServices(stack *node.Node, config *params.NodeConfig, db *leveldb.DB) error { - // Register eth-node node bridge - err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { - return &nodebridge.NodeService{Node: gethbridge.NewNodeBridge(stack)}, nil - }) - if err != nil { - return fmt.Errorf("failed to register NodeBridge: %v", err) - } - - // start Waku service - if err := activateWakuService(stack, config, db); err != nil { - return fmt.Errorf("%v: %v", ErrWakuServiceRegistrationFailure, err) - } - - if err := activateWakuV2Service(stack, config, db); err != nil { - return fmt.Errorf("%v: %v", ErrWakuV2ServiceRegistrationFailure, err) - } - - // start peer service - if err := activatePeerService(stack); err != nil { - return fmt.Errorf("%v: %v", ErrPeerServiceRegistrationFailure, err) - } - return nil -} - // newGethNodeConfig returns default stack configuration for mobile client node func newGethNodeConfig(config *params.NodeConfig) (*node.Config, error) { nc := &node.Config{ @@ -164,11 +77,12 @@ func newGethNodeConfig(config *params.NodeConfig) (*node.Config, error) { Name: config.Name, Version: config.Version, P2P: p2p.Config{ - NoDiscovery: true, // we always use only v5 server - ListenAddr: config.ListenAddr, - NAT: nat.Any(), - MaxPeers: config.MaxPeers, - MaxPendingPeers: config.MaxPendingPeers, + NoDiscovery: true, // we always use only v5 server + ListenAddr: config.ListenAddr, + NAT: nat.Any(), + // FIX ME: don't hardcode + MaxPeers: 200, + MaxPendingPeers: 200, }, HTTPModules: config.FormatAPIModules(), } @@ -214,7 +128,7 @@ func calculateGenesis(networkID uint64) (*core.Genesis, error) { case params.MainNetworkID: genesis = core.DefaultGenesisBlock() case params.RopstenNetworkID: - genesis = core.DefaultTestnetGenesisBlock() + genesis = core.DefaultRopstenGenesisBlock() case params.RinkebyNetworkID: genesis = core.DefaultRinkebyGenesisBlock() case params.GoerliNetworkID: @@ -246,191 +160,6 @@ func defaultStatusChainGenesisBlock() (*core.Genesis, error) { return genesis, nil } -// activateLightEthService configures and registers the eth.Ethereum service with a given node. -func activateLightEthService(stack *node.Node, accs *accounts.Manager, config *params.NodeConfig) error { - if !config.LightEthConfig.Enabled { - logger.Info("LES protocol is disabled") - return nil - } - - genesis, err := calculateGenesis(config.NetworkID) - if err != nil { - return err - } - - ethConf := eth.DefaultConfig - ethConf.Genesis = genesis - ethConf.SyncMode = downloader.LightSync - ethConf.NetworkId = config.NetworkID - ethConf.DatabaseCache = config.LightEthConfig.DatabaseCache - return stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { - // NOTE(dshulyak) here we set our instance of the accounts manager. - // without sharing same instance selected account won't be visible for personal_* methods. - nctx := &node.ServiceContext{} - *nctx = *ctx - nctx.AccountManager = accs - return les.New(nctx, ðConf) - }) -} - -func activatePersonalService(stack *node.Node, accs *accounts.Manager, config *params.NodeConfig) error { - return stack.Register(func(*node.ServiceContext) (node.Service, error) { - svc := personal.New(accs) - return svc, nil - }) -} - -func activatePeerService(stack *node.Node) error { - return stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { - svc := peer.New() - return svc, nil - }) -} - -func registerWakuMailServer(wakuService *waku.Waku, config *params.WakuConfig) (err error) { - var mailServer mailserver.WakuMailServer - wakuService.RegisterMailServer(&mailServer) - - return mailServer.Init(wakuService, config) -} - -// activateWakuService configures Waku and adds it to the given node. -func activateWakuService(stack *node.Node, config *params.NodeConfig, db *leveldb.DB) (err error) { - if !config.WakuConfig.Enabled { - logger.Info("Waku protocol is disabled") - return nil - } - - err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { - return createWakuService(ctx, &config.WakuConfig, &config.ClusterConfig) - }) - if err != nil { - return - } - - // Register Whisper eth-node bridge - err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { - var ethnode *nodebridge.NodeService - if err := ctx.Service(ðnode); err != nil { - return nil, err - } - w, err := ethnode.Node.GetWaku(ctx) - if err != nil { - return nil, err - } - return &nodebridge.WakuService{Waku: w}, nil - }) - if err != nil { - return - } - - // TODO(dshulyak) add a config option to enable it by default, but disable if app is started from statusd - return stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { - var ethnode *nodebridge.NodeService - if err := ctx.Service(ðnode); err != nil { - return nil, err - } - return wakuext.New(config.ShhextConfig, ethnode.Node, ctx, ext.EnvelopeSignalHandler{}, db), nil - }) -} - -// activateWakuV2Service configures WakuV2 and adds it to the given node. -func activateWakuV2Service(stack *node.Node, config *params.NodeConfig, db *leveldb.DB) (err error) { - if !config.WakuV2Config.Enabled { - logger.Info("WakuV2 protocol is disabled") - return nil - } - - err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { - return createWakuV2Service(ctx, config.NodeKey, &config.WakuV2Config, &config.ClusterConfig) - }) - if err != nil { - return - } - - return stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { - var ethnode *nodebridge.NodeService - if err := ctx.Service(ðnode); err != nil { - return nil, err - } - return wakuv2ext.New(config.ShhextConfig, ethnode.Node, ctx, ext.EnvelopeSignalHandler{}, db), nil - }) -} - -func createWakuService(ctx *node.ServiceContext, wakuCfg *params.WakuConfig, clusterCfg *params.ClusterConfig) (*waku.Waku, error) { - cfg := &waku.Config{ - MaxMessageSize: wakucommon.DefaultMaxMessageSize, - BloomFilterMode: wakuCfg.BloomFilterMode, - FullNode: wakuCfg.FullNode, - SoftBlacklistedPeerIDs: wakuCfg.SoftBlacklistedPeerIDs, - MinimumAcceptedPoW: params.WakuMinimumPoW, - EnableConfirmations: wakuCfg.EnableConfirmations, - } - - if wakuCfg.MaxMessageSize > 0 { - cfg.MaxMessageSize = wakuCfg.MaxMessageSize - } - if wakuCfg.MinimumPoW > 0 { - cfg.MinimumAcceptedPoW = wakuCfg.MinimumPoW - } - - w := waku.New(cfg, logutils.ZapLogger()) - - if wakuCfg.EnableRateLimiter { - r := wakuRateLimiter(wakuCfg, clusterCfg) - w.RegisterRateLimiter(r) - } - - if timesource, err := timeSource(ctx); err == nil { - w.SetTimeSource(timesource) - } - - // enable mail service - if wakuCfg.EnableMailServer { - if err := registerWakuMailServer(w, wakuCfg); err != nil { - return nil, fmt.Errorf("failed to register WakuMailServer: %v", err) - } - } - - if wakuCfg.LightClient { - emptyBloomFilter := make([]byte, 64) - if err := w.SetBloomFilter(emptyBloomFilter); err != nil { - return nil, err - } - } - - return w, nil -} - -func createWakuV2Service(ctx *node.ServiceContext, nodeKey string, wakuCfg *params.WakuV2Config, clusterCfg *params.ClusterConfig) (*wakuv2.Waku, error) { - cfg := &wakuv2.Config{ - MaxMessageSize: wakucommon.DefaultMaxMessageSize, - SoftBlacklistedPeerIDs: wakuCfg.SoftBlacklistedPeerIDs, - Host: wakuCfg.Host, - Port: wakuCfg.Port, - BootNodes: clusterCfg.WakuNodes, - StoreNodes: clusterCfg.WakuStoreNodes, - } - - if wakuCfg.MaxMessageSize > 0 { - cfg.MaxMessageSize = wakuCfg.MaxMessageSize - } - - lvl, err := logging.LevelFromString("info") - if err != nil { - panic(err) - } - logging.SetAllLoggers(lvl) - - w, err := wakuv2.New(nodeKey, cfg, logutils.ZapLogger()) - - if err != nil { - return nil, err - } - - return w, nil -} - // parseNodes creates list of enode.Node out of enode strings. func parseNodes(enodes []string) []*enode.Node { var nodes []*enode.Node @@ -469,6 +198,7 @@ func parseNodesToNodeID(enodes []string) []enode.ID { return nodeIDs } +/* // timeSource get timeSource to be used by whisper func timeSource(ctx *node.ServiceContext) (func() time.Time, error) { var timeSource *timesource.NTPTimeSource @@ -476,33 +206,4 @@ func timeSource(ctx *node.ServiceContext) (func() time.Time, error) { return nil, err } return timeSource.Now, nil -} - -func wakuRateLimiter(wakuCfg *params.WakuConfig, clusterCfg *params.ClusterConfig) *wakucommon.PeerRateLimiter { - enodes := append( - parseNodes(clusterCfg.StaticNodes), - parseNodes(clusterCfg.TrustedMailServers)..., - ) - var ( - ips []string - peerIDs []enode.ID - ) - for _, item := range enodes { - ips = append(ips, item.IP().String()) - peerIDs = append(peerIDs, item.ID()) - } - return wakucommon.NewPeerRateLimiter( - &wakucommon.PeerRateLimiterConfig{ - PacketLimitPerSecIP: wakuCfg.PacketRateLimitIP, - PacketLimitPerSecPeerID: wakuCfg.PacketRateLimitPeerID, - BytesLimitPerSecIP: wakuCfg.BytesRateLimitIP, - BytesLimitPerSecPeerID: wakuCfg.BytesRateLimitPeerID, - WhitelistedIPs: ips, - WhitelistedPeerIDs: peerIDs, - }, - &wakucommon.MetricsRateLimiterHandler{}, - &wakucommon.DropPeerRateLimiterHandler{ - Tolerance: wakuCfg.RateLimitTolerance, - }, - ) -} +}*/ diff --git a/node/status_node_services.go b/node/status_node_services.go new file mode 100644 index 000000000..ab015f288 --- /dev/null +++ b/node/status_node_services.go @@ -0,0 +1,472 @@ +package node + +import ( + "errors" + "fmt" + + logging "github.com/ipfs/go-log" + + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/p2p/enode" + + "github.com/status-im/status-go/appmetrics" + "github.com/status-im/status-go/common" + gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" + "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/logutils" + "github.com/status-im/status-go/mailserver" + "github.com/status-im/status-go/multiaccounts/accounts" + "github.com/status-im/status-go/params" + "github.com/status-im/status-go/rpc" + accountssvc "github.com/status-im/status-go/services/accounts" + appmetricsservice "github.com/status-im/status-go/services/appmetrics" + "github.com/status-im/status-go/services/browsers" + "github.com/status-im/status-go/services/ext" + localnotifications "github.com/status-im/status-go/services/local-notifications" + "github.com/status-im/status-go/services/mailservers" + "github.com/status-im/status-go/services/nodebridge" + "github.com/status-im/status-go/services/peer" + "github.com/status-im/status-go/services/permissions" + "github.com/status-im/status-go/services/personal" + "github.com/status-im/status-go/services/rpcfilters" + "github.com/status-im/status-go/services/rpcstats" + "github.com/status-im/status-go/services/subscriptions" + "github.com/status-im/status-go/services/wakuext" + "github.com/status-im/status-go/services/wakuv2ext" + "github.com/status-im/status-go/services/wallet" + "github.com/status-im/status-go/timesource" + "github.com/status-im/status-go/waku" + wakucommon "github.com/status-im/status-go/waku/common" + "github.com/status-im/status-go/wakuv2" +) + +var ( + // ErrWakuClearIdentitiesFailure clearing whisper identities has failed. + ErrWakuClearIdentitiesFailure = errors.New("failed to clear waku identities") +) + +func (b *StatusNode) initServices(config *params.NodeConfig) error { + accountsFeed := &event.Feed{} + + services := []common.StatusService{} + services = appendIf(config.UpstreamConfig.Enabled, services, b.rpcFiltersService()) + services = append(services, b.subscriptionService()) + services = append(services, b.rpcStatsService()) + services = append(services, b.appmetricsService()) + services = append(services, b.peerService()) + services = append(services, b.personalService()) + services = appendIf(config.EnableNTPSync, services, b.timeSource()) + services = appendIf(b.appDB != nil && b.multiaccountsDB != nil, services, b.accountsService(accountsFeed)) + services = appendIf(config.BrowsersConfig.Enabled, services, b.browsersService()) + services = appendIf(config.PermissionsConfig.Enabled, services, b.permissionsService()) + services = appendIf(config.MailserversConfig.Enabled, services, b.mailserversService()) + if config.WakuConfig.Enabled { + wakuService, err := b.wakuService(&config.WakuConfig, &config.ClusterConfig) + if err != nil { + return err + } + + services = append(services, wakuService) + + wakuext, err := b.wakuExtService(config) + if err != nil { + return err + } + + b.wakuExtSrvc = wakuext + + services = append(services, wakuext) + } + + if config.WakuV2Config.Enabled { + waku2Service, err := b.wakuV2Service(config.NodeKey, &config.WakuV2Config, &config.ClusterConfig) + if err != nil { + return err + } + services = append(services, waku2Service) + + wakuext, err := b.wakuV2ExtService(config) + if err != nil { + return err + } + + b.wakuV2ExtSrvc = wakuext + + services = append(services, wakuext) + } + + b.log.Info("WAKU ENABLED") + + if config.WalletConfig.Enabled { + walletService := b.walletService(config.NetworkID, accountsFeed) + b.log.Info("SETTING REPC CLIETN") + b.walletSrvc.SetClient(b.rpcClient.Ethclient()) + b.log.Info("SET REPC CLIETN") + services = append(services, walletService) + } + + b.log.Info("WALLET ENABLED") + + // We ignore for now local notifications flag as users who are upgrading have no mean to enable it + services = append(services, b.localNotificationsService(config.NetworkID)) + + b.log.Info("SET CLIENT") + + b.peerSrvc.SetDiscoverer(b) + + b.log.Info("SET DISCOVERER") + + for i := range services { + b.gethNode.RegisterAPIs(services[i].APIs()) + b.gethNode.RegisterProtocols(services[i].Protocols()) + b.gethNode.RegisterLifecycle(services[i]) + } + + return nil +} + +func (b *StatusNode) nodeBridge() types.Node { + return gethbridge.NewNodeBridge(b.gethNode, b.wakuSrvc, b.wakuV2Srvc) +} + +func (b *StatusNode) nodeBridgeService() *nodebridge.NodeService { + if b.nodeBridgeSrvc == nil { + b.nodeBridgeSrvc = &nodebridge.NodeService{Node: b.nodeBridge()} + } + return b.nodeBridgeSrvc +} + +func (b *StatusNode) wakuExtService(config *params.NodeConfig) (*wakuext.Service, error) { + if b.gethNode == nil { + return nil, errors.New("geth node not initialized") + } + + if b.wakuExtSrvc == nil { + b.wakuExtSrvc = wakuext.New(config.ShhextConfig, b.nodeBridge(), ext.EnvelopeSignalHandler{}, b.db) + } + + b.wakuExtSrvc.SetP2PServer(b.gethNode.Server()) + return b.wakuExtSrvc, nil +} + +func (b *StatusNode) wakuV2ExtService(config *params.NodeConfig) (*wakuv2ext.Service, error) { + if b.gethNode == nil { + return nil, errors.New("geth node not initialized") + } + if b.wakuV2ExtSrvc == nil { + b.wakuV2ExtSrvc = wakuv2ext.New(config.ShhextConfig, b.nodeBridge(), ext.EnvelopeSignalHandler{}, b.db) + } + + b.wakuV2ExtSrvc.SetP2PServer(b.gethNode.Server()) + return b.wakuV2ExtSrvc, nil +} + +func (b *StatusNode) WakuService() *waku.Waku { + return b.wakuSrvc +} + +func (b *StatusNode) WakuExtService() *wakuext.Service { + return b.wakuExtSrvc +} + +func (b *StatusNode) WakuV2ExtService() *wakuv2ext.Service { + return b.wakuV2ExtSrvc +} +func (b *StatusNode) WakuV2Service() *wakuv2.Waku { + return b.wakuV2Srvc +} + +func (b *StatusNode) wakuService(wakuCfg *params.WakuConfig, clusterCfg *params.ClusterConfig) (*waku.Waku, error) { + if b.wakuSrvc == nil { + cfg := &waku.Config{ + MaxMessageSize: wakucommon.DefaultMaxMessageSize, + BloomFilterMode: wakuCfg.BloomFilterMode, + FullNode: wakuCfg.FullNode, + SoftBlacklistedPeerIDs: wakuCfg.SoftBlacklistedPeerIDs, + MinimumAcceptedPoW: params.WakuMinimumPoW, + EnableConfirmations: wakuCfg.EnableConfirmations, + } + + if wakuCfg.MaxMessageSize > 0 { + cfg.MaxMessageSize = wakuCfg.MaxMessageSize + } + if wakuCfg.MinimumPoW > 0 { + cfg.MinimumAcceptedPoW = wakuCfg.MinimumPoW + } + + w := waku.New(cfg, logutils.ZapLogger()) + + if wakuCfg.EnableRateLimiter { + r := wakuRateLimiter(wakuCfg, clusterCfg) + w.RegisterRateLimiter(r) + } + + if timesource := b.timeSource(); timesource != nil { + w.SetTimeSource(timesource.Now) + } + + // enable mail service + if wakuCfg.EnableMailServer { + if err := registerWakuMailServer(w, wakuCfg); err != nil { + return nil, fmt.Errorf("failed to register WakuMailServer: %v", err) + } + } + + if wakuCfg.LightClient { + emptyBloomFilter := make([]byte, 64) + if err := w.SetBloomFilter(emptyBloomFilter); err != nil { + return nil, err + } + } + b.wakuSrvc = w + } + return b.wakuSrvc, nil + +} + +func (b *StatusNode) wakuV2Service(nodeKey string, wakuCfg *params.WakuV2Config, clusterCfg *params.ClusterConfig) (*wakuv2.Waku, error) { + if b.wakuV2Srvc == nil { + cfg := &wakuv2.Config{ + MaxMessageSize: wakucommon.DefaultMaxMessageSize, + SoftBlacklistedPeerIDs: wakuCfg.SoftBlacklistedPeerIDs, + Host: wakuCfg.Host, + Port: wakuCfg.Port, + BootNodes: clusterCfg.WakuNodes, + StoreNodes: clusterCfg.WakuStoreNodes, + } + + if wakuCfg.MaxMessageSize > 0 { + cfg.MaxMessageSize = wakuCfg.MaxMessageSize + } + + lvl, err := logging.LevelFromString("info") + if err != nil { + panic(err) + } + logging.SetAllLoggers(lvl) + + w, err := wakuv2.New(nodeKey, cfg, logutils.ZapLogger()) + + if err != nil { + return nil, err + } + b.wakuV2Srvc = w + } + + return b.wakuV2Srvc, nil +} + +func wakuRateLimiter(wakuCfg *params.WakuConfig, clusterCfg *params.ClusterConfig) *wakucommon.PeerRateLimiter { + enodes := append( + parseNodes(clusterCfg.StaticNodes), + parseNodes(clusterCfg.TrustedMailServers)..., + ) + var ( + ips []string + peerIDs []enode.ID + ) + for _, item := range enodes { + ips = append(ips, item.IP().String()) + peerIDs = append(peerIDs, item.ID()) + } + return wakucommon.NewPeerRateLimiter( + &wakucommon.PeerRateLimiterConfig{ + PacketLimitPerSecIP: wakuCfg.PacketRateLimitIP, + PacketLimitPerSecPeerID: wakuCfg.PacketRateLimitPeerID, + BytesLimitPerSecIP: wakuCfg.BytesRateLimitIP, + BytesLimitPerSecPeerID: wakuCfg.BytesRateLimitPeerID, + WhitelistedIPs: ips, + WhitelistedPeerIDs: peerIDs, + }, + &wakucommon.MetricsRateLimiterHandler{}, + &wakucommon.DropPeerRateLimiterHandler{ + Tolerance: wakuCfg.RateLimitTolerance, + }, + ) +} + +func (b *StatusNode) rpcFiltersService() *rpcfilters.Service { + if b.rpcFiltersSrvc == nil { + b.rpcFiltersSrvc = rpcfilters.New(b) + } + return b.rpcFiltersSrvc +} + +func (b *StatusNode) subscriptionService() *subscriptions.Service { + if b.subscriptionsSrvc == nil { + + b.subscriptionsSrvc = subscriptions.New(func() *rpc.Client { return b.RPCPrivateClient() }) + } + return b.subscriptionsSrvc +} + +func (b *StatusNode) rpcStatsService() *rpcstats.Service { + if b.rpcStatsSrvc == nil { + b.rpcStatsSrvc = rpcstats.New() + } + + return b.rpcStatsSrvc +} + +func (b *StatusNode) accountsService(accountsFeed *event.Feed) *accountssvc.Service { + if b.accountsSrvc == nil { + b.accountsSrvc = accountssvc.NewService(accounts.NewDB(b.appDB), b.multiaccountsDB, b.gethAccountManager.Manager, accountsFeed) + } + + return b.accountsSrvc +} + +func (b *StatusNode) browsersService() *browsers.Service { + if b.browsersSrvc == nil { + b.browsersSrvc = browsers.NewService(browsers.NewDB(b.appDB)) + } + return b.browsersSrvc +} + +func (b *StatusNode) permissionsService() *permissions.Service { + if b.permissionsSrvc == nil { + b.permissionsSrvc = permissions.NewService(permissions.NewDB(b.appDB)) + } + return b.permissionsSrvc +} + +func (b *StatusNode) mailserversService() *mailservers.Service { + if b.mailserversSrvc == nil { + + b.mailserversSrvc = mailservers.NewService(mailservers.NewDB(b.appDB)) + } + return b.mailserversSrvc +} + +func (b *StatusNode) appmetricsService() common.StatusService { + if b.appMetricsSrvc == nil { + b.appMetricsSrvc = appmetricsservice.NewService(appmetrics.NewDB(b.appDB)) + } + return b.appMetricsSrvc +} + +func (b *StatusNode) walletService(network uint64, accountsFeed *event.Feed) common.StatusService { + if b.walletSrvc == nil { + b.walletSrvc = wallet.NewService(wallet.NewDB(b.appDB, network), accountsFeed) + } + return b.walletSrvc +} + +func (b *StatusNode) localNotificationsService(network uint64) *localnotifications.Service { + if b.localNotificationsSrvc == nil { + b.localNotificationsSrvc = localnotifications.NewService(b.appDB, network) + } + return b.localNotificationsSrvc +} + +func (b *StatusNode) peerService() *peer.Service { + if b.peerSrvc == nil { + b.peerSrvc = peer.New() + } + return b.peerSrvc + +} + +func registerWakuMailServer(wakuService *waku.Waku, config *params.WakuConfig) (err error) { + var mailServer mailserver.WakuMailServer + wakuService.RegisterMailServer(&mailServer) + + return mailServer.Init(wakuService, config) +} + +func appendIf(condition bool, services []common.StatusService, service common.StatusService) []common.StatusService { + if !condition { + return services + } + return append(services, service) +} + +func (b *StatusNode) RPCFiltersService() *rpcfilters.Service { + return b.rpcFiltersSrvc +} + +func (b *StatusNode) StopLocalNotifications() error { + if b.localNotificationsSrvc == nil { + return nil + } + + if b.localNotificationsSrvc.IsStarted() { + err := b.localNotificationsSrvc.Stop() + if err != nil { + b.log.Error("LocalNotifications service stop failed on StopLocalNotifications", "error", err) + return nil + } + } + + return nil +} + +func (b *StatusNode) StartLocalNotifications() error { + if b.localNotificationsSrvc == nil { + return nil + } + + if b.walletSrvc == nil { + return nil + } + + if !b.localNotificationsSrvc.IsStarted() { + err := b.localNotificationsSrvc.Start() + + if err != nil { + b.log.Error("LocalNotifications service start failed on StartLocalNotifications", "error", err) + return nil + } + } + + err := b.localNotificationsSrvc.SubscribeWallet(b.walletSrvc.GetFeed()) + + if err != nil { + b.log.Error("LocalNotifications service could not subscribe to wallet on StartLocalNotifications", "error", err) + return nil + } + + return nil +} + +// `personal_sign` and `personal_ecRecover` methods are important to +// keep DApps working. +// Usually, they are provided by an ETH or a LES service, but when using +// upstream, we don't start any of these, so we need to start our own +// implementation. + +func (b *StatusNode) personalService() *personal.Service { + if b.personalSrvc == nil { + b.personalSrvc = personal.New(b.accountsManager) + } + return b.personalSrvc +} + +func (b *StatusNode) timeSource() *timesource.NTPTimeSource { + + if b.timeSourceSrvc == nil { + b.timeSourceSrvc = timesource.Default() + } + return b.timeSourceSrvc +} + +func (b *StatusNode) Cleanup() error { + if b.wakuSrvc != nil { + if err := b.wakuSrvc.DeleteKeyPairs(); err != nil { + return fmt.Errorf("%s: %v", ErrWakuClearIdentitiesFailure, err) + } + } + + if b.Config().WalletConfig.Enabled { + if b.walletSrvc != nil { + if b.walletSrvc.IsStarted() { + err := b.walletSrvc.Stop() + if err != nil { + return err + } + } + } + } + return nil + +} diff --git a/params/config.go b/params/config.go index ed880a64a..1b752aa19 100644 --- a/params/config.go +++ b/params/config.go @@ -17,14 +17,36 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/discv5" + "github.com/ethereum/go-ethereum/params" "github.com/status-im/status-go/eth-node/crypto" + "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/protocol/pushnotificationserver" "github.com/status-im/status-go/static" wakucommon "github.com/status-im/status-go/waku/common" wakuv2common "github.com/status-im/status-go/wakuv2/common" ) +// ---------- +// LightEthConfig +// ---------- + +// LightEthConfig holds LES-related configuration +// Status nodes are always lightweight clients (due to mobile platform constraints) +type LightEthConfig struct { + // Enabled flag specifies whether protocol is enabled + Enabled bool + + // DatabaseCache is memory (in MBs) allocated to internal caching (min 16MB / database forced) + DatabaseCache int + + // TrustedNodes is a list of trusted servers + TrustedNodes []string + + //MinTrustedFraction is minimum percentage of connected trusted servers to validate header(1-100) + MinTrustedFraction int +} + // ---------- // DatabaseConfig // ---------- @@ -412,6 +434,9 @@ type NodeConfig struct { // ClusterConfig extra configuration for supporting cluster peers. ClusterConfig ClusterConfig `json:"ClusterConfig," validate:"structonly"` + // LightEthConfig extra configuration for LES + LightEthConfig LightEthConfig `json:"LightEthConfig," validate:"structonly"` + // WakuConfig provides a configuration for Waku subprotocol. WakuConfig WakuConfig `json:"WakuConfig" validate:"structonly"` @@ -705,6 +730,9 @@ func (c *NodeConfig) updatePeerLimits() { if c.NoDiscovery && !c.Rendezvous { return } + if c.LightEthConfig.Enabled { + c.RequireTopics[discv5.Topic(LesTopic(int(c.NetworkID)))] = LesDiscoveryLimits + } } // NewNodeConfig creates new node configuration object with bare-minimum defaults. @@ -739,6 +767,9 @@ func NewNodeConfig(dataDir string, networkID uint64) (*NodeConfig, error) { UpstreamConfig: UpstreamRPCConfig{ URL: getUpstreamURL(networkID), }, + LightEthConfig: LightEthConfig{ + DatabaseCache: 16, + }, WakuConfig: WakuConfig{ DataDir: wakuDir, MinimumPoW: WakuMinimumPoW, @@ -840,6 +871,10 @@ func (c *NodeConfig) Validate() error { } } + if c.UpstreamConfig.Enabled && c.LightEthConfig.Enabled { + return fmt.Errorf("both UpstreamConfig and LightEthConfig are enabled, but they are mutually exclusive") + } + if err := c.validateChildStructs(validate); err != nil { return err } @@ -889,6 +924,9 @@ func (c *NodeConfig) validateChildStructs(validate *validator.Validate) error { if err := c.ClusterConfig.Validate(validate); err != nil { return err } + if err := c.LightEthConfig.Validate(validate); err != nil { + return err + } if err := c.SwarmConfig.Validate(validate); err != nil { return err } @@ -928,6 +966,19 @@ func (c *ClusterConfig) Validate(validate *validator.Validate) error { return nil } +// Validate validates the LightEthConfig struct and returns an error if inconsistent values are found +func (c *LightEthConfig) Validate(validate *validator.Validate) error { + if !c.Enabled { + return nil + } + + if err := validate.Struct(c); err != nil { + return err + } + + return nil +} + // Validate validates the SwarmConfig struct and returns an error if inconsistent values are found func (c *SwarmConfig) Validate(validate *validator.Validate) error { if !c.Enabled { @@ -995,3 +1046,18 @@ func (c *NodeConfig) FormatAPIModules() []string { func (c *NodeConfig) AddAPIModule(m string) { c.APIModules = fmt.Sprintf("%s,%s", c.APIModules, m) } + +// LesTopic returns discovery v5 topic derived from genesis of the provided network. +// 1 - mainnet, 3 - ropsten, 4 - rinkeby +func LesTopic(netid int) string { + switch netid { + case 1: + return LESDiscoveryIdentifier + types.Bytes2Hex(params.MainnetGenesisHash.Bytes()[:8]) + case 3: + return LESDiscoveryIdentifier + types.Bytes2Hex(params.RopstenGenesisHash.Bytes()[:8]) + case 4: + return LESDiscoveryIdentifier + types.Bytes2Hex(params.RinkebyGenesisHash.Bytes()[:8]) + default: + return "" + } +} diff --git a/peers/peerpool_test.go b/peers/peerpool_test.go index 75dd45bfd..c383c7518 100644 --- a/peers/peerpool_test.go +++ b/peers/peerpool_test.go @@ -128,7 +128,7 @@ func (s *PeerPoolSimulationSuite) TestPeerPoolCacheEthV5() { config := map[discv5.Topic]params.Limits{ topic: params.NewLimits(1, 1), } - peerPoolOpts := &Options{100 * time.Millisecond, 100 * time.Millisecond, 0, true, 100 * time.Millisecond, nil, ""} + peerPoolOpts := &Options{100 * time.Millisecond, 100 * time.Millisecond, 0, true, 100 * time.Millisecond, nil} cache, err := newInMemoryCache() s.Require().NoError(err) peerPool := NewPeerPool(s.discovery[1], config, cache, peerPoolOpts) @@ -177,7 +177,7 @@ func TestPeerPoolMaxPeersOverflow(t *testing.T) { defer func() { assert.NoError(t, discovery.Stop()) }() require.True(t, discovery.Running()) - poolOpts := &Options{DefaultFastSync, DefaultSlowSync, 0, true, 100 * time.Millisecond, nil, ""} + poolOpts := &Options{DefaultFastSync, DefaultSlowSync, 0, true, 100 * time.Millisecond, nil} pool := NewPeerPool(discovery, nil, nil, poolOpts) require.NoError(t, pool.Start(peer, nil)) require.Equal(t, signal.EventDiscoveryStarted, <-signals) @@ -230,7 +230,7 @@ func TestPeerPoolDiscV5Timeout(t *testing.T) { require.True(t, discovery.Running()) // start PeerPool - poolOpts := &Options{DefaultFastSync, DefaultSlowSync, time.Millisecond * 100, true, 100 * time.Millisecond, nil, ""} + poolOpts := &Options{DefaultFastSync, DefaultSlowSync, time.Millisecond * 100, true, 100 * time.Millisecond, nil} pool := NewPeerPool(discovery, nil, nil, poolOpts) require.NoError(t, pool.Start(server, nil)) require.Equal(t, signal.EventDiscoveryStarted, <-signals) @@ -277,7 +277,7 @@ func TestPeerPoolNotAllowedStopping(t *testing.T) { require.True(t, discovery.Running()) // start PeerPool - poolOpts := &Options{DefaultFastSync, DefaultSlowSync, time.Millisecond * 100, false, 100 * time.Millisecond, nil, ""} + poolOpts := &Options{DefaultFastSync, DefaultSlowSync, time.Millisecond * 100, false, 100 * time.Millisecond, nil} pool := NewPeerPool(discovery, nil, nil, poolOpts) require.NoError(t, pool.Start(server, nil)) @@ -294,7 +294,7 @@ func (s *PeerPoolSimulationSuite) TestUpdateTopicLimits() { config := map[discv5.Topic]params.Limits{ topic: params.NewLimits(1, 1), } - peerPoolOpts := &Options{100 * time.Millisecond, 100 * time.Millisecond, 0, true, 100 * time.Millisecond, nil, ""} + peerPoolOpts := &Options{100 * time.Millisecond, 100 * time.Millisecond, 0, true, 100 * time.Millisecond, nil} cache, err := newInMemoryCache() s.Require().NoError(err) peerPool := NewPeerPool(s.discovery[1], config, cache, peerPoolOpts) @@ -373,7 +373,6 @@ func (s *PeerPoolSimulationSuite) TestMailServerPeersDiscovery() { true, 100 * time.Millisecond, []enode.ID{s.peers[0].Self().ID()}, - "", } peerPool := NewPeerPool(s.discovery[1], config, cache, peerPoolOpts) s.Require().NoError(peerPool.Start(s.peers[1], nil)) diff --git a/protocol/messenger.go b/protocol/messenger.go index c411847ec..b01a57262 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -206,8 +206,7 @@ func NewMessenger( // Initialize transport layer. var transp *transport.Transport - logger.Info("failed to find Whisper service; trying Waku", zap.Error(err)) - + logger.Info("TEST", zap.Any("node", node)) if waku, err := node.GetWaku(nil); err == nil && waku != nil { transp, err = transport.NewTransport( waku, diff --git a/services/accounts/service.go b/services/accounts/service.go index 4e272732b..3c47a390b 100644 --- a/services/accounts/service.go +++ b/services/accounts/service.go @@ -24,7 +24,7 @@ type Service struct { } // Start a service. -func (s *Service) Start(*p2p.Server) error { +func (s *Service) Start() error { return nil } diff --git a/services/appmetrics/service.go b/services/appmetrics/service.go index fdd364b93..614236fea 100644 --- a/services/appmetrics/service.go +++ b/services/appmetrics/service.go @@ -15,7 +15,7 @@ type Service struct { db *appmetrics.Database } -func (s *Service) Start(*p2p.Server) error { +func (s *Service) Start() error { return nil } diff --git a/services/browsers/service.go b/services/browsers/service.go index 463d301e2..907c8223f 100644 --- a/services/browsers/service.go +++ b/services/browsers/service.go @@ -16,7 +16,7 @@ type Service struct { } // Start a service. -func (s *Service) Start(*p2p.Server) error { +func (s *Service) Start() error { return nil } diff --git a/services/ext/service.go b/services/ext/service.go index 245403195..39bd843ff 100644 --- a/services/ext/service.go +++ b/services/ext/service.go @@ -64,7 +64,7 @@ type Service struct { } // Make sure that Service implements node.Service interface. -var _ node.Service = (*Service)(nil) +var _ node.Lifecycle = (*Service)(nil) func New( config params.ShhextConfig, @@ -209,7 +209,7 @@ func (c *verifyTransactionClient) TransactionByHash(ctx context.Context, hash ty return coretypes.Message{}, coretypes.TransactionStatusPending, err } - message, err := transaction.AsMessage(signer) + message, err := transaction.AsMessage(signer, nil) if err != nil { return coretypes.Message{}, coretypes.TransactionStatusPending, err } @@ -328,10 +328,15 @@ func (s *Service) APIs() []rpc.API { panic("this is abstract service, use shhext or wakuext implementation") } +func (s *Service) SetP2PServer(server *p2p.Server) { + s.server = server +} + // Start is run when a service is started. // It does nothing in this case but is required by `node.Service` interface. -func (s *Service) Start(server *p2p.Server) error { - s.server = server +func (s *Service) Start() error { + // TODO: set server before start + // s.server = server return nil } diff --git a/services/local-notifications/core.go b/services/local-notifications/core.go index 7970b3c45..f6b181294 100644 --- a/services/local-notifications/core.go +++ b/services/local-notifications/core.go @@ -153,7 +153,7 @@ func pushMessage(notification *Notification) { } // Start Worker which processes all incoming messages -func (s *Service) Start(_ *p2p.Server) error { +func (s *Service) Start() error { s.started = true s.transmitter.quit = make(chan struct{}) diff --git a/services/mailservers/service.go b/services/mailservers/service.go index 7e11a7c11..75209f8bf 100644 --- a/services/mailservers/service.go +++ b/services/mailservers/service.go @@ -13,7 +13,7 @@ type Service struct { db *Database } -func (s *Service) Start(*p2p.Server) error { +func (s *Service) Start() error { return nil } diff --git a/services/permissions/service.go b/services/permissions/service.go index 96f41a477..28adcf20f 100644 --- a/services/permissions/service.go +++ b/services/permissions/service.go @@ -15,7 +15,7 @@ type Service struct { } // Start a service. -func (s *Service) Start(*p2p.Server) error { +func (s *Service) Start() error { return nil } diff --git a/services/personal/service.go b/services/personal/service.go index f5cf99790..69c7c89f2 100644 --- a/services/personal/service.go +++ b/services/personal/service.go @@ -9,7 +9,7 @@ import ( ) // Make sure that Service implements node.Service interface. -var _ node.Service = (*Service)(nil) +var _ node.Lifecycle = (*Service)(nil) // Service represents out own implementation of personal sign operations. type Service struct { @@ -40,7 +40,7 @@ func (s *Service) APIs() []rpc.API { // Start is run when a service is started. // It does nothing in this case but is required by `node.Service` interface. -func (s *Service) Start(server *p2p.Server) error { +func (s *Service) Start() error { return nil } diff --git a/services/rpcstats/service.go b/services/rpcstats/service.go index e55c990a6..43e62f0ab 100644 --- a/services/rpcstats/service.go +++ b/services/rpcstats/service.go @@ -32,7 +32,7 @@ func (s *Service) Protocols() []p2p.Protocol { // Start is run when a service is started. // It does nothing in this case but is required by `node.Service` interface. -func (s *Service) Start(server *p2p.Server) error { +func (s *Service) Start() error { resetStats() return nil } diff --git a/services/status/account_mock.go b/services/status/account_mock.go deleted file mode 100644 index 6b3edfb88..000000000 --- a/services/status/account_mock.go +++ /dev/null @@ -1,124 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: services/status/service.go - -// Package status is a generated GoMock package. -package status - -import ( - ecdsa "crypto/ecdsa" - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - - account "github.com/status-im/status-go/account" - "github.com/status-im/status-go/account/generator" - types "github.com/status-im/status-go/eth-node/types" -) - -// MockWhisperService is a mock of WhisperService interface -type MockWhisperService struct { - ctrl *gomock.Controller - recorder *MockWhisperServiceMockRecorder -} - -// MockWhisperServiceMockRecorder is the mock recorder for MockWhisperService -type MockWhisperServiceMockRecorder struct { - mock *MockWhisperService -} - -// NewMockWhisperService creates a new mock instance -func NewMockWhisperService(ctrl *gomock.Controller) *MockWhisperService { - mock := &MockWhisperService{ctrl: ctrl} - mock.recorder = &MockWhisperServiceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockWhisperService) EXPECT() *MockWhisperServiceMockRecorder { - return m.recorder -} - -// AddKeyPair mocks base method -func (m *MockWhisperService) AddKeyPair(key *ecdsa.PrivateKey) (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddKeyPair", key) - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// AddKeyPair indicates an expected call of AddKeyPair -func (mr *MockWhisperServiceMockRecorder) AddKeyPair(key interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddKeyPair", reflect.TypeOf((*MockWhisperService)(nil).AddKeyPair), key) -} - -// MockAccountManager is a mock of AccountManager interface -type MockAccountManager struct { - ctrl *gomock.Controller - recorder *MockAccountManagerMockRecorder -} - -// MockAccountManagerMockRecorder is the mock recorder for MockAccountManager -type MockAccountManagerMockRecorder struct { - mock *MockAccountManager -} - -// NewMockAccountManager creates a new mock instance -func NewMockAccountManager(ctrl *gomock.Controller) *MockAccountManager { - mock := &MockAccountManager{ctrl: ctrl} - mock.recorder = &MockAccountManagerMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockAccountManager) EXPECT() *MockAccountManagerMockRecorder { - return m.recorder -} - -// AddressToDecryptedAccount mocks base method -func (m *MockAccountManager) AddressToDecryptedAccount(arg0, arg1 string) (types.Account, *types.Key, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddressToDecryptedAccount", arg0, arg1) - ret0, _ := ret[0].(types.Account) - ret1, _ := ret[1].(*types.Key) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// AddressToDecryptedAccount indicates an expected call of AddressToDecryptedAccount -func (mr *MockAccountManagerMockRecorder) AddressToDecryptedAccount(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddressToDecryptedAccount", reflect.TypeOf((*MockAccountManager)(nil).AddressToDecryptedAccount), arg0, arg1) -} - -// SelectAccount mocks base method -func (m *MockAccountManager) SelectAccount(arg0 account.LoginParams) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SelectAccount", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// SelectAccount indicates an expected call of SelectAccount -func (mr *MockAccountManagerMockRecorder) SelectAccount(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SelectAccount", reflect.TypeOf((*MockAccountManager)(nil).SelectAccount), arg0) -} - -// CreateAccount mocks base method -func (m *MockAccountManager) CreateAccount(password string) (generator.GeneratedAccountInfo, account.Info, string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateAccount", password) - ret0, _ := ret[0].(generator.GeneratedAccountInfo) - ret1, _ := ret[1].(account.Info) - ret2, _ := ret[2].(string) - ret3, _ := ret[3].(error) - return ret0, ret1, ret2, ret3 -} - -// CreateAccount indicates an expected call of CreateAccount -func (mr *MockAccountManagerMockRecorder) CreateAccount(password interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAccount", reflect.TypeOf((*MockAccountManager)(nil).CreateAccount), password) -} diff --git a/services/status/api.go b/services/status/api.go deleted file mode 100644 index 467390957..000000000 --- a/services/status/api.go +++ /dev/null @@ -1,106 +0,0 @@ -package status - -import ( - "context" - "errors" - "fmt" - - "github.com/status-im/status-go/account" - - "github.com/status-im/status-go/eth-node/types" -) - -// PublicAPI represents a set of APIs from the `web3.status` namespace. -type PublicAPI struct { - s *Service -} - -// NewAPI creates an instance of the status API. -func NewAPI(s *Service) *PublicAPI { - return &PublicAPI{s: s} -} - -// LoginRequest : json request for status_login. -type LoginRequest struct { - Addr string `json:"address"` - Password string `json:"password"` -} - -// LoginResponse : json response returned by status_login. -type LoginResponse struct { - AddressKeyID string `json:"address_key_id"` -} - -// Login is an implementation of `status_login` or `web3.status.login` API -func (api *PublicAPI) Login(context context.Context, req LoginRequest) (res LoginResponse, err error) { - _, accountKey, err := api.s.am.AddressToDecryptedAccount(req.Addr, req.Password) - if err != nil { - return - } - - if res.AddressKeyID, err = api.s.w.AddKeyPair(accountKey.PrivateKey); err != nil { - return - } - - loginParams := account.LoginParams{ - ChatAddress: types.HexToAddress(req.Addr), - Password: req.Password, - MainAccount: types.HexToAddress(req.Addr), - } - if err = api.s.am.SelectAccount(loginParams); err != nil { - return - } - - return -} - -// SignupRequest : json request for status_signup. -type SignupRequest struct { - Password string `json:"password"` -} - -// SignupResponse : json response returned by status_signup. -type SignupResponse struct { - Address string `json:"address"` - Pubkey string `json:"pubkey"` - WalletAddress string `json:"walletAddress"` - WalletPubkey string `json:"walletPubKey"` - ChatAddress string `json:"chatAddress"` - ChatPubkey string `json:"chatPubkey"` - Mnemonic string `json:"mnemonic"` -} - -// Signup is an implementation of `status_signup` or `web3.status.signup` API -func (api *PublicAPI) Signup(context context.Context, req SignupRequest) (res SignupResponse, err error) { - _, accountInfo, mnemonic, err := api.s.am.CreateAccount(req.Password) - if err != nil { - err = errors.New("could not create the specified account : " + err.Error()) - return - } - - res.Address = accountInfo.WalletAddress - res.Pubkey = accountInfo.WalletPubKey - res.WalletAddress = accountInfo.WalletAddress - res.WalletPubkey = accountInfo.WalletPubKey - res.ChatAddress = accountInfo.ChatAddress - res.ChatPubkey = accountInfo.ChatPubKey - res.Mnemonic = mnemonic - - return -} - -// CreateAddressResponse : json response returned by status_createaccount -type CreateAddressResponse struct { - Address string `json:"address"` - Pubkey string `json:"pubkey"` - Privkey string `json:"privkey"` -} - -// CreateAddress is an implementation of `status_createaccount` or `web3.status.createaccount` API -func (api *PublicAPI) CreateAddress(context context.Context) (res CreateAddressResponse, err error) { - if res.Address, res.Pubkey, res.Privkey, err = account.CreateAddress(); err != nil { - err = fmt.Errorf("could not create an address: %v", err) - } - - return -} diff --git a/services/status/api_test.go b/services/status/api_test.go deleted file mode 100644 index cfb647e31..000000000 --- a/services/status/api_test.go +++ /dev/null @@ -1,178 +0,0 @@ -package status - -import ( - "context" - "crypto/ecdsa" - "errors" - "testing" - - "github.com/status-im/status-go/account/generator" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/suite" - - "github.com/status-im/status-go/account" - "github.com/status-im/status-go/eth-node/types" -) - -func TestStatusSuite(t *testing.T) { - suite.Run(t, new(StatusSuite)) -} - -type StatusSuite struct { - suite.Suite - am *MockAccountManager - w *MockWhisperService - api *PublicAPI -} - -func (s *StatusSuite) SetupTest() { - ctrl := gomock.NewController(s.T()) - s.am = NewMockAccountManager(ctrl) - s.w = NewMockWhisperService(ctrl) - service := New(s.w) - service.SetAccountManager(s.am) - - s.api = NewAPI(service) -} - -var logintests = []struct { - name string - expectedAddressKey string - expectedError error - prepareExpectations func(*StatusSuite) -}{ - { - name: "success login", - expectedAddressKey: "addressKey", - expectedError: nil, - prepareExpectations: func(s *StatusSuite) { - key := types.Key{ - PrivateKey: &ecdsa.PrivateKey{}, - } - s.am.EXPECT().AddressToDecryptedAccount("0x01", "password").Return(types.Account{}, &key, nil) - s.w.EXPECT().AddKeyPair(key.PrivateKey).Return("addressKey", nil) - - loginParams := account.LoginParams{ - MainAccount: types.HexToAddress("0x01"), - ChatAddress: types.HexToAddress("0x01"), - Password: "password", - } - s.am.EXPECT().SelectAccount(loginParams).Return(nil) - }, - }, - { - name: "error when decrypting account from address", - expectedAddressKey: "", - expectedError: errors.New("foo"), - prepareExpectations: func(s *StatusSuite) { - key := types.Key{ - PrivateKey: &ecdsa.PrivateKey{}, - } - s.am.EXPECT().AddressToDecryptedAccount("0x01", "password").Return(types.Account{}, &key, errors.New("foo")) - }, - }, - { - name: "error when adding key pair to whisper", - expectedAddressKey: "", - expectedError: errors.New("foo"), - prepareExpectations: func(s *StatusSuite) { - key := types.Key{ - PrivateKey: &ecdsa.PrivateKey{}, - } - s.am.EXPECT().AddressToDecryptedAccount("0x01", "password").Return(types.Account{}, &key, nil) - s.w.EXPECT().AddKeyPair(key.PrivateKey).Return("", errors.New("foo")) - }, - }, - { - name: "error when selecting account", - expectedAddressKey: "", - expectedError: errors.New("foo"), - prepareExpectations: func(s *StatusSuite) { - key := types.Key{ - PrivateKey: &ecdsa.PrivateKey{}, - } - s.am.EXPECT().AddressToDecryptedAccount("0x01", "password").Return(types.Account{}, &key, nil) - s.w.EXPECT().AddKeyPair(key.PrivateKey).Return("", nil) - - loginParams := account.LoginParams{ - MainAccount: types.HexToAddress("0x01"), - ChatAddress: types.HexToAddress("0x01"), - Password: "password", - } - s.am.EXPECT().SelectAccount(loginParams).Return(errors.New("foo")) - }, - }, -} - -func (s *StatusSuite) TestLogin() { - for _, t := range logintests { - req := LoginRequest{Addr: "0x01", Password: "password"} - - t.prepareExpectations(s) - - var ctx context.Context - res, err := s.api.Login(ctx, req) - s.Equal(t.expectedAddressKey, res.AddressKeyID, "failed scenario : "+t.name) - s.Equal(t.expectedError, err, "failed scenario : "+t.name) - } -} - -var signuptests = []struct { - name string - expectedResponse SignupResponse - expectedError error - prepareExpectations func(*StatusSuite) -}{ - { - name: "success signup", - expectedResponse: SignupResponse{ - WalletAddress: "addr", - WalletPubkey: "pubkey", - Mnemonic: "mnemonic", - }, - expectedError: nil, - prepareExpectations: func(s *StatusSuite) { - mKInfo := generator.GeneratedAccountInfo{ - IdentifiedAccountInfo: generator.IdentifiedAccountInfo{}, - Mnemonic: "", - } - accountInfo := account.Info{ - WalletAddress: "addr", - WalletPubKey: "pubkey", - ChatAddress: "addr", - ChatPubKey: "pubkey", - } - s.am.EXPECT().CreateAccount("password").Return(mKInfo, accountInfo, "mnemonic", nil) - }, - }, - { - name: "success signup", - expectedResponse: SignupResponse{ - WalletAddress: "", - WalletPubkey: "", - Mnemonic: "", - }, - expectedError: errors.New("could not create the specified account : foo"), - prepareExpectations: func(s *StatusSuite) { - mKInfo := generator.GeneratedAccountInfo{ - IdentifiedAccountInfo: generator.IdentifiedAccountInfo{}, - Mnemonic: "", - } - s.am.EXPECT().CreateAccount("password").Return(mKInfo, account.Info{}, "", errors.New("foo")) - }, - }, -} - -func (s *StatusSuite) TestSignup() { - for _, t := range signuptests { - t.prepareExpectations(s) - - var ctx context.Context - res, err := s.api.Signup(ctx, SignupRequest{Password: "password"}) - s.Equal(t.expectedResponse.WalletAddress, res.WalletAddress, "failed scenario : "+t.name) - s.Equal(t.expectedResponse.WalletPubkey, res.WalletPubkey, "failed scenario : "+t.name) - s.Equal(t.expectedResponse.Mnemonic, res.Mnemonic, "failed scenario : "+t.name) - s.Equal(t.expectedError, err, "failed scenario : "+t.name) - } -} diff --git a/services/status/service.go b/services/status/service.go deleted file mode 100644 index aed81eba2..000000000 --- a/services/status/service.go +++ /dev/null @@ -1,74 +0,0 @@ -package status - -import ( - "crypto/ecdsa" - - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/rpc" - - "github.com/status-im/status-go/account" - "github.com/status-im/status-go/account/generator" - "github.com/status-im/status-go/eth-node/types" -) - -// Make sure that Service implements node.Service interface. -var _ node.Service = (*Service)(nil) - -// WhisperService whisper interface to add key pairs -type WhisperService interface { - AddKeyPair(key *ecdsa.PrivateKey) (string, error) -} - -// AccountManager interface to manage account actions -type AccountManager interface { - AddressToDecryptedAccount(string, string) (types.Account, *types.Key, error) - SelectAccount(account.LoginParams) error - CreateAccount(password string) (mkInfo generator.GeneratedAccountInfo, accountInfo account.Info, mnemonic string, err error) -} - -// Service represents our own implementation of status status operations. -type Service struct { - am AccountManager - w WhisperService -} - -// New returns a new Service. -func New(w WhisperService) *Service { - return &Service{w: w} -} - -// Protocols returns a new protocols list. In this case, there are none. -func (s *Service) Protocols() []p2p.Protocol { - return []p2p.Protocol{} -} - -// APIs returns a list of new APIs. -func (s *Service) APIs() []rpc.API { - - return []rpc.API{ - { - Namespace: "status", - Version: "1.0", - Service: NewAPI(s), - Public: false, - }, - } -} - -// SetAccountManager sets account manager for the API calls. -func (s *Service) SetAccountManager(a AccountManager) { - s.am = a -} - -// Start is run when a service is started. -// It does nothing in this case but is required by `node.Service` interface. -func (s *Service) Start(server *p2p.Server) error { - return nil -} - -// Stop is run when a service is stopped. -// It does nothing in this case but is required by `node.Service` interface. -func (s *Service) Stop() error { - return nil -} diff --git a/services/wakuext/service.go b/services/wakuext/service.go index f70e35b64..6358685f5 100644 --- a/services/wakuext/service.go +++ b/services/wakuext/service.go @@ -15,8 +15,8 @@ type Service struct { w types.Waku } -func New(config params.ShhextConfig, n types.Node, ctx interface{}, handler ext.EnvelopeEventsHandler, ldb *leveldb.DB) *Service { - w, err := n.GetWaku(ctx) +func New(config params.ShhextConfig, n types.Node, handler ext.EnvelopeEventsHandler, ldb *leveldb.DB) *Service { + w, err := n.GetWaku(nil) if err != nil { panic(err) } diff --git a/services/wakuv2ext/service.go b/services/wakuv2ext/service.go index b11b05b0a..e108a47d3 100644 --- a/services/wakuv2ext/service.go +++ b/services/wakuv2ext/service.go @@ -15,8 +15,8 @@ type Service struct { w types.Waku } -func New(config params.ShhextConfig, n types.Node, ctx interface{}, handler ext.EnvelopeEventsHandler, ldb *leveldb.DB) *Service { - w, err := n.GetWakuV2(ctx) +func New(config params.ShhextConfig, n types.Node, handler ext.EnvelopeEventsHandler, ldb *leveldb.DB) *Service { + w, err := n.GetWakuV2(nil) if err != nil { panic(err) } diff --git a/services/wallet/service.go b/services/wallet/service.go index 3c7b02e7a..f748e3d22 100644 --- a/services/wallet/service.go +++ b/services/wallet/service.go @@ -43,7 +43,7 @@ type Service struct { } // Start signals transmitter. -func (s *Service) Start(*p2p.Server) error { +func (s *Service) Start() error { s.group = NewGroup(context.Background()) return s.signals.Start() } diff --git a/timesource/timesource.go b/timesource/timesource.go index 639999272..dbe7c6a3e 100644 --- a/timesource/timesource.go +++ b/timesource/timesource.go @@ -194,7 +194,7 @@ func (s *NTPTimeSource) StartService() error { } // Start runs a goroutine that updates local offset every updatePeriod. -func (s *NTPTimeSource) Start(*p2p.Server) error { +func (s *NTPTimeSource) Start() error { return s.runPeriodically(s.updateOffset) } diff --git a/vendor/github.com/ethereum/go-ethereum/les/client.go b/vendor/github.com/ethereum/go-ethereum/les/client.go index 1d8a2c6f9..39169d772 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/client.go +++ b/vendor/github.com/ethereum/go-ethereum/les/client.go @@ -43,9 +43,7 @@ import ( "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" ) @@ -203,37 +201,13 @@ func (s *LightEthereum) VfluxRequest(n *enode.Node, reqs vflux.Requests) vflux.R if !s.udpEnabled { return nil } - reqsEnc, _ := rlp.EncodeToBytes(&reqs) - repliesEnc, _ := s.p2pServer.DiscV5.TalkRequest(s.serverPool.DialNode(n), "vfx", reqsEnc) - var replies vflux.Replies - if len(repliesEnc) == 0 || rlp.DecodeBytes(repliesEnc, &replies) != nil { - return nil - } - return replies + return nil } // vfxVersion returns the version number of the "les" service subdomain of the vflux UDP // service, as advertised in the ENR record func (s *LightEthereum) vfxVersion(n *enode.Node) uint { - if n.Seq() == 0 { - var err error - if !s.udpEnabled { - return 0 - } - if n, err = s.p2pServer.DiscV5.RequestENR(n); n != nil && err == nil && n.Seq() != 0 { - s.serverPool.Persist(n) - } else { - return 0 - } - } - - var les []rlp.RawValue - if err := n.Load(enr.WithEntry("les", &les)); err != nil || len(les) < 1 { - return 0 - } - var version uint - rlp.DecodeBytes(les[0], &version) // Ignore additional fields (for forward compatibility). - return version + return 0 } // prenegQuery sends a capacity query to the given server node to determine whether diff --git a/vendor/github.com/ethereum/go-ethereum/les/enr_entry.go b/vendor/github.com/ethereum/go-ethereum/les/enr_entry.go index 307313fb1..b1e71bed0 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/enr_entry.go +++ b/vendor/github.com/ethereum/go-ethereum/les/enr_entry.go @@ -54,11 +54,6 @@ func (eth *LightEthereum) setupDiscovery() (enode.Iterator, error) { it.AddSource(dns) } - // Enable DHT. - if eth.udpEnabled { - it.AddSource(eth.p2pServer.DiscV5.RandomNodes()) - } - forkFilter := forkid.NewFilter(eth.blockchain) iterator := enode.Filter(it, func(n *enode.Node) bool { return nodeIsServer(forkFilter, n) }) return iterator, nil diff --git a/vendor/github.com/ethereum/go-ethereum/les/server.go b/vendor/github.com/ethereum/go-ethereum/les/server.go index c135e65f2..520879a8c 100644 --- a/vendor/github.com/ethereum/go-ethereum/les/server.go +++ b/vendor/github.com/ethereum/go-ethereum/les/server.go @@ -201,9 +201,10 @@ func (s *LesServer) Start() error { s.handler.start() s.wg.Add(1) go s.capacityManagement() - if s.p2pSrv.DiscV5 != nil { - s.p2pSrv.DiscV5.RegisterTalkHandler("vfx", s.vfluxServer.ServeEncoded) - } + /* + if s.p2pSrv.DiscV5 != nil { + s.p2pSrv.DiscV5.RegisterTalkHandler("vfx", s.vfluxServer.ServeEncoded) + }*/ return nil } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/dial.go b/vendor/github.com/ethereum/go-ethereum/p2p/dial.go index d36d66550..b008de3c4 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/dial.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/dial.go @@ -206,6 +206,7 @@ func (d *dialScheduler) removeStatic(n *enode.Node) { // peerAdded updates the peer set. func (d *dialScheduler) peerAdded(c *conn) { + log.Info("PEER added") select { case d.addPeerCh <- c: case <-d.ctx.Done(): @@ -214,6 +215,7 @@ func (d *dialScheduler) peerAdded(c *conn) { // peerRemoved updates the peer set. func (d *dialScheduler) peerRemoved(c *conn) { + log.Info("PEER removed") select { case d.remPeerCh <- c: case <-d.ctx.Done(): @@ -243,7 +245,7 @@ loop: select { case node := <-nodesCh: if err := d.checkDial(node); err != nil { - d.log.Trace("Discarding dial candidate", "id", node.ID(), "ip", node.IP(), "reason", err) + d.log.Info("Discarding dial candidate", "id", node.ID(), "ip", node.IP(), "reason", err) } else { d.startDial(newDialTask(node, dynDialedConn)) } @@ -277,14 +279,22 @@ loop: case node := <-d.addStaticCh: id := node.ID() _, exists := d.static[id] - d.log.Trace("Adding static node", "id", id, "ip", node.IP(), "added", !exists) + d.log.Info("Adding static node", "id", id, "ip", node.IP(), "added", !exists) if exists { + d.log.Info("existing, continue") continue loop } task := newDialTask(node, staticDialedConn) + d.log.Info("new dial task") d.static[id] = task - if d.checkDial(node) == nil { + d.log.Info("checking dial") + err := d.checkDial(node) + d.log.Info("dial checked") + if err == nil { + d.log.Info("addign to static pool") d.addToStaticPool(task) + } else { + d.log.Info("error", "err", err) } case node := <-d.remStaticCh: @@ -376,6 +386,7 @@ func (d *dialScheduler) expireHistory() { // freeDialSlots returns the number of free dial slots. The result can be negative // when peers are connected while their task is still running. func (d *dialScheduler) freeDialSlots() int { + log.Info("checkign slots", "max dials", d.maxDialPeers, "dial peers", d.dialPeers) slots := (d.maxDialPeers - d.dialPeers) * 2 if slots > d.maxActiveDials { slots = d.maxActiveDials @@ -412,7 +423,9 @@ func (d *dialScheduler) checkDial(n *enode.Node) error { // startStaticDials starts n static dial tasks. func (d *dialScheduler) startStaticDials(n int) (started int) { + log.Info("starting", "n", n) for started = 0; started < n && len(d.staticPool) > 0; started++ { + log.Info("starting static") idx := d.rand.Intn(len(d.staticPool)) task := d.staticPool[idx] d.startDial(task) diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/README b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/README new file mode 100644 index 000000000..617a473d7 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/README @@ -0,0 +1,4 @@ +This package is an early prototype of Discovery v5. Do not use this code. + +See https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md for the +current Discovery v5 specification. \ No newline at end of file diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/database.go b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/database.go index 3c2d5744c..ca118e7f8 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/database.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/database.go @@ -58,12 +58,11 @@ var ( nodeDBVersionKey = []byte("version") // Version of the database to flush if changes nodeDBItemPrefix = []byte("n:") // Identifier to prefix node entries with - nodeDBDiscoverRoot = ":discover" - nodeDBDiscoverPing = nodeDBDiscoverRoot + ":lastping" - nodeDBDiscoverPong = nodeDBDiscoverRoot + ":lastpong" - nodeDBDiscoverFindFails = nodeDBDiscoverRoot + ":findfail" - nodeDBDiscoverLocalEndpoint = nodeDBDiscoverRoot + ":localendpoint" - nodeDBTopicRegTickets = ":tickets" + nodeDBDiscoverRoot = ":discover" + nodeDBDiscoverPing = nodeDBDiscoverRoot + ":lastping" + nodeDBDiscoverPong = nodeDBDiscoverRoot + ":lastpong" + nodeDBDiscoverFindFails = nodeDBDiscoverRoot + ":findfail" + nodeDBTopicRegTickets = ":tickets" ) // newNodeDB creates a new node database for storing and retrieving infos about @@ -311,20 +310,6 @@ func (db *nodeDB) updateFindFails(id NodeID, fails int) error { return db.storeInt64(makeKey(id, nodeDBDiscoverFindFails), int64(fails)) } -// localEndpoint returns the last local endpoint communicated to the -// given remote node. -func (db *nodeDB) localEndpoint(id NodeID) *rpcEndpoint { - var ep rpcEndpoint - if err := db.fetchRLP(makeKey(id, nodeDBDiscoverLocalEndpoint), &ep); err != nil { - return nil - } - return &ep -} - -func (db *nodeDB) updateLocalEndpoint(id NodeID, ep rpcEndpoint) error { - return db.storeRLP(makeKey(id, nodeDBDiscoverLocalEndpoint), &ep) -} - // querySeeds retrieves random nodes to be used as potential seed nodes // for bootstrapping. func (db *nodeDB) querySeeds(n int, maxAge time.Duration) []*Node { diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/net.go b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/net.go index de7d8de6a..53e00a388 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/net.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/net.go @@ -77,14 +77,6 @@ type Network struct { nursery []*Node nodes map[NodeID]*Node // tracks active nodes with state != known timeoutTimers map[timeoutEvent]*time.Timer - - // Revalidation queues. - // Nodes put on these queues will be pinged eventually. - slowRevalidateQueue []*Node - fastRevalidateQueue []*Node - - // Buffers for state transition. - sendBuf []*ingressPacket } // transport is implemented by the UDP transport. @@ -104,10 +96,9 @@ type transport interface { } type findnodeQuery struct { - remote *Node - target common.Hash - reply chan<- []*Node - nresults int // counter for received nodes + remote *Node + target common.Hash + reply chan<- []*Node } type topicRegisterReq struct { @@ -366,6 +357,8 @@ func (net *Network) loop() { bucketRefreshTimer = time.NewTimer(bucketRefreshInterval) refreshDone chan struct{} // closed when the 'refresh' lookup has ended ) + defer refreshTimer.Stop() + defer bucketRefreshTimer.Stop() // Tracking the next ticket to register. var ( @@ -402,11 +395,13 @@ func (net *Network) loop() { searchInfo = make(map[Topic]topicSearchInfo) activeSearchCount int ) + defer topicRegisterLookupTick.Stop() topicSearchLookupDone := make(chan topicSearchResult, 100) topicSearch := make(chan Topic, 100) <-topicRegisterLookupTick.C statsDump := time.NewTicker(10 * time.Second) + defer statsDump.Stop() loop: for { @@ -646,14 +641,14 @@ loop: } log.Trace("loop stopped") - log.Debug(fmt.Sprintf("shutting down")) + log.Debug("shutting down") if net.conn != nil { net.conn.Close() } - if refreshDone != nil { - // TODO: wait for pending refresh. - //<-refreshResults - } + // TODO: wait for pending refresh. + // if refreshDone != nil { + // <-refreshResults + // } // Cancel all pending timeouts. for _, timer := range net.timeoutTimers { timer.Stop() @@ -1042,6 +1037,9 @@ func (net *Network) handle(n *Node, ev nodeEvent, pkt *ingressPacket) error { net.db.ensureExpirer() } } + if ev == pongTimeout { + n.pingEcho = nil // clean up if pongtimeout + } if n.state == nil { n.state = unknown //??? } diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/node.go b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/node.go index 3d4748512..44d3025b7 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/node.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/node.go @@ -66,23 +66,6 @@ func (n *Node) addr() *net.UDPAddr { return &net.UDPAddr{IP: n.IP, Port: int(n.UDP)} } -func (n *Node) setAddr(a *net.UDPAddr) { - n.IP = a.IP - if ipv4 := a.IP.To4(); ipv4 != nil { - n.IP = ipv4 - } - n.UDP = uint16(a.Port) -} - -// compares the given address against the stored values. -func (n *Node) addrEqual(a *net.UDPAddr) bool { - ip := a.IP - if ipv4 := a.IP.To4(); ipv4 != nil { - ip = ipv4 - } - return n.UDP == uint16(a.Port) && n.IP.Equal(ip) -} - // Incomplete returns true for nodes with no IP address. func (n *Node) Incomplete() bool { return n.IP == nil @@ -326,14 +309,6 @@ func (n NodeID) Pubkey() (*ecdsa.PublicKey, error) { return p, nil } -func (id NodeID) mustPubkey() ecdsa.PublicKey { - pk, err := id.Pubkey() - if err != nil { - panic(err) - } - return *pk -} - // recoverNodeID computes the public key used to sign the // given hash from the signature. func recoverNodeID(hash, sig []byte) (id NodeID, err error) { diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/ntp.go b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/ntp.go deleted file mode 100644 index 4fb5f657a..000000000 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/ntp.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -// Contains the NTP time drift detection via the SNTP protocol: -// https://tools.ietf.org/html/rfc4330 - -package discv5 - -import ( - "fmt" - "net" - "sort" - "strings" - "time" - - "github.com/ethereum/go-ethereum/log" -) - -const ( - ntpPool = "pool.ntp.org" // ntpPool is the NTP server to query for the current time - ntpChecks = 3 // Number of measurements to do against the NTP server -) - -// durationSlice attaches the methods of sort.Interface to []time.Duration, -// sorting in increasing order. -type durationSlice []time.Duration - -func (s durationSlice) Len() int { return len(s) } -func (s durationSlice) Less(i, j int) bool { return s[i] < s[j] } -func (s durationSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -// checkClockDrift queries an NTP server for clock drifts and warns the user if -// one large enough is detected. -func checkClockDrift() { - drift, err := sntpDrift(ntpChecks) - if err != nil { - return - } - if drift < -driftThreshold || drift > driftThreshold { - warning := fmt.Sprintf("System clock seems off by %v, which can prevent network connectivity", drift) - howtofix := fmt.Sprintf("Please enable network time synchronisation in system settings") - separator := strings.Repeat("-", len(warning)) - - log.Warn(separator) - log.Warn(warning) - log.Warn(howtofix) - log.Warn(separator) - } else { - log.Debug(fmt.Sprintf("Sanity NTP check reported %v drift, all ok", drift)) - } -} - -// sntpDrift does a naive time resolution against an NTP server and returns the -// measured drift. This method uses the simple version of NTP. It's not precise -// but should be fine for these purposes. -// -// Note, it executes two extra measurements compared to the number of requested -// ones to be able to discard the two extremes as outliers. -func sntpDrift(measurements int) (time.Duration, error) { - // Resolve the address of the NTP server - addr, err := net.ResolveUDPAddr("udp", ntpPool+":123") - if err != nil { - return 0, err - } - // Construct the time request (empty package with only 2 fields set): - // Bits 3-5: Protocol version, 3 - // Bits 6-8: Mode of operation, client, 3 - request := make([]byte, 48) - request[0] = 3<<3 | 3 - - // Execute each of the measurements - drifts := []time.Duration{} - for i := 0; i < measurements+2; i++ { - // Dial the NTP server and send the time retrieval request - conn, err := net.DialUDP("udp", nil, addr) - if err != nil { - return 0, err - } - defer conn.Close() - - sent := time.Now() - if _, err = conn.Write(request); err != nil { - return 0, err - } - // Retrieve the reply and calculate the elapsed time - conn.SetDeadline(time.Now().Add(5 * time.Second)) - - reply := make([]byte, 48) - if _, err = conn.Read(reply); err != nil { - return 0, err - } - elapsed := time.Since(sent) - - // Reconstruct the time from the reply data - sec := uint64(reply[43]) | uint64(reply[42])<<8 | uint64(reply[41])<<16 | uint64(reply[40])<<24 - frac := uint64(reply[47]) | uint64(reply[46])<<8 | uint64(reply[45])<<16 | uint64(reply[44])<<24 - - nanosec := sec*1e9 + (frac*1e9)>>32 - - t := time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC).Add(time.Duration(nanosec)).Local() - - // Calculate the drift based on an assumed answer time of RRT/2 - drifts = append(drifts, sent.Sub(t)+elapsed/2) - } - // Calculate average drif (drop two extremities to avoid outliers) - sort.Sort(durationSlice(drifts)) - - drift := time.Duration(0) - for i := 1; i < len(drifts)-1; i++ { - drift += drifts[i] - } - return drift / time.Duration(measurements), nil -} diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/table.go b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/table.go index 4f4b2426f..64c3ecd1c 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/table.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/table.go @@ -14,12 +14,8 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package discv5 implements the RLPx v5 Topic Discovery Protocol. -// -// The Topic Discovery protocol provides a way to find RLPx nodes that -// can be connected to. It uses a Kademlia-like protocol to maintain a -// distributed database of the IDs and endpoints of all listening -// nodes. +// Package discv5 is a prototype implementation of Discvery v5. +// Deprecated: do not use this package. package discv5 import ( diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/ticket.go b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/ticket.go index ae4b18e7c..c5e3d6c08 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/ticket.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/ticket.go @@ -22,7 +22,6 @@ import ( "fmt" "math" "math/rand" - "sort" "time" "github.com/ethereum/go-ethereum/common" @@ -33,8 +32,6 @@ import ( const ( ticketTimeBucketLen = time.Minute - timeWindow = 10 // * ticketTimeBucketLen - wantTicketsInWindow = 10 collectFrequency = time.Second * 30 registerFrequency = time.Second * 60 maxCollectDebt = 10 @@ -139,7 +136,6 @@ type ticketStore struct { lastBucketFetched timeBucket nextTicketCached *ticketRef - nextTicketReg mclock.AbsTime searchTopicMap map[Topic]searchTopic nextTopicQueryCleanup mclock.AbsTime @@ -268,57 +264,6 @@ func (s *ticketStore) nextSearchLookup(topic Topic) lookupInfo { return target } -// ticketsInWindow returns the tickets of a given topic in the registration window. -func (s *ticketStore) ticketsInWindow(topic Topic) []ticketRef { - // Sanity check that the topic still exists before operating on it - if s.tickets[topic] == nil { - log.Warn("Listing non-existing discovery tickets", "topic", topic) - return nil - } - // Gather all the tickers in the next time window - var tickets []ticketRef - - buckets := s.tickets[topic].buckets - for idx := timeBucket(0); idx < timeWindow; idx++ { - tickets = append(tickets, buckets[s.lastBucketFetched+idx]...) - } - log.Trace("Retrieved discovery registration tickets", "topic", topic, "from", s.lastBucketFetched, "tickets", len(tickets)) - return tickets -} - -func (s *ticketStore) removeExcessTickets(t Topic) { - tickets := s.ticketsInWindow(t) - if len(tickets) <= wantTicketsInWindow { - return - } - sort.Sort(ticketRefByWaitTime(tickets)) - for _, r := range tickets[wantTicketsInWindow:] { - s.removeTicketRef(r) - } -} - -type ticketRefByWaitTime []ticketRef - -// Len is the number of elements in the collection. -func (s ticketRefByWaitTime) Len() int { - return len(s) -} - -func (ref ticketRef) waitTime() mclock.AbsTime { - return ref.t.regTime[ref.idx] - ref.t.issueTime -} - -// Less reports whether the element with -// index i should sort before the element with index j. -func (s ticketRefByWaitTime) Less(i, j int) bool { - return s[i].waitTime() < s[j].waitTime() -} - -// Swap swaps the elements with indexes i and j. -func (s ticketRefByWaitTime) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - func (s *ticketStore) addTicketRef(r ticketRef) { topic := r.t.topics[r.idx] tickets := s.tickets[topic] @@ -565,15 +510,6 @@ func (s *ticketStore) addTicket(localTime mclock.AbsTime, pingHash []byte, ticke } } -func (s *ticketStore) getNodeTicket(node *Node) *ticket { - if s.nodes[node] == nil { - log.Trace("Retrieving node ticket", "node", node.ID, "serial", nil) - } else { - log.Trace("Retrieving node ticket", "node", node.ID, "serial", s.nodes[node].serial) - } - return s.nodes[node] -} - func (s *ticketStore) canQueryTopic(node *Node, topic Topic) bool { qq := s.queriesSent[node] if qq != nil { @@ -770,12 +706,6 @@ func globalRandRead(b []byte) { } } -func (r *topicRadius) isInRadius(addrHash common.Hash) bool { - nodePrefix := binary.BigEndian.Uint64(addrHash[0:8]) - dist := nodePrefix ^ r.topicHashPrefix - return dist < r.radius -} - func (r *topicRadius) chooseLookupBucket(a, b int) int { if a < 0 { a = 0 diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/udp.go b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/udp.go index ff5ed983b..088f95cac 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/discv5/udp.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/discv5/udp.go @@ -27,7 +27,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/netutil" "github.com/ethereum/go-ethereum/rlp" ) @@ -38,15 +37,12 @@ const Version = 4 var ( errPacketTooSmall = errors.New("too small") errBadPrefix = errors.New("bad prefix") - errTimeout = errors.New("RPC timeout") ) // Timeouts const ( respTimeout = 500 * time.Millisecond expiration = 20 * time.Second - - driftThreshold = 10 * time.Second // Allowed clock drift before warning user ) // RPC request structures @@ -187,10 +183,6 @@ func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint { return rpcEndpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort} } -func (e1 rpcEndpoint) equal(e2 rpcEndpoint) bool { - return e1.UDP == e2.UDP && e1.TCP == e2.TCP && e1.IP.Equal(e2.IP) -} - func nodeFromRPC(sender *net.UDPAddr, rn rpcNode) (*Node, error) { if err := netutil.CheckRelayIP(sender.IP, rn.IP); err != nil { return nil, err @@ -225,7 +217,6 @@ type udp struct { conn conn priv *ecdsa.PrivateKey ourEndpoint rpcEndpoint - nat nat.Interface net *Network } @@ -274,13 +265,6 @@ func (t *udp) sendPing(remote *Node, toaddr *net.UDPAddr, topics []Topic) (hash return hash } -func (t *udp) sendFindnode(remote *Node, target NodeID) { - t.sendPacket(remote.ID, remote.addr(), byte(findnodePacket), findnode{ - Target: target, - Expiration: uint64(time.Now().Add(expiration).Unix()), - }) -} - func (t *udp) sendNeighbours(remote *Node, results []*Node) { // Send neighbors in chunks with at most maxNeighbors per packet // to stay below the 1280 byte limit. diff --git a/vendor/github.com/ethereum/go-ethereum/p2p/server.go b/vendor/github.com/ethereum/go-ethereum/p2p/server.go index 9c86de8d8..214cb636e 100644 --- a/vendor/github.com/ethereum/go-ethereum/p2p/server.go +++ b/vendor/github.com/ethereum/go-ethereum/p2p/server.go @@ -35,6 +35,7 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/discv5" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/p2p/nat" @@ -104,7 +105,7 @@ type Config struct { // BootstrapNodesV5 are used to establish connectivity // with the rest of the network using the V5 discovery // protocol. - BootstrapNodesV5 []*enode.Node `toml:",omitempty"` + BootstrapNodesV5 []*discv5.Node `toml:",omitempty"` // Static nodes are used as pre-configured connections which are always // maintained and re-connected on disconnects. @@ -181,7 +182,7 @@ type Server struct { nodedb *enode.DB localnode *enode.LocalNode ntab *discover.UDPv4 - DiscV5 *discover.UDPv5 + DiscV5 *discv5.Network discmix *enode.FairMix dialsched *dialScheduler @@ -442,7 +443,7 @@ type sharedUDPConn struct { unhandled chan discover.ReadPacket } -// ReadFromUDP implements discover.UDPConn +// ReadFromUDP implements discv5.conn func (s *sharedUDPConn) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) { packet, ok := <-s.unhandled if !ok { @@ -456,7 +457,7 @@ func (s *sharedUDPConn) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err err return l, packet.Addr, nil } -// Close implements discover.UDPConn +// Close implements discv5.conn func (s *sharedUDPConn) Close() error { return nil } @@ -615,7 +616,7 @@ func (srv *Server) setupDiscovery() error { Unhandled: unhandled, Log: srv.log, } - ntab, err := discover.ListenV4(conn, srv.localnode, cfg) + ntab, err := discover.ListenUDP(conn, srv.localnode, cfg) if err != nil { return err } @@ -625,21 +626,20 @@ func (srv *Server) setupDiscovery() error { // Discovery V5 if srv.DiscoveryV5 { - cfg := discover.Config{ - PrivateKey: srv.PrivateKey, - NetRestrict: srv.NetRestrict, - Bootnodes: srv.BootstrapNodesV5, - Log: srv.log, - } + var ntab *discv5.Network var err error if sconn != nil { - srv.DiscV5, err = discover.ListenV5(sconn, srv.localnode, cfg) + ntab, err = discv5.ListenUDP(srv.PrivateKey, sconn, "", srv.NetRestrict) } else { - srv.DiscV5, err = discover.ListenV5(conn, srv.localnode, cfg) + ntab, err = discv5.ListenUDP(srv.PrivateKey, conn, "", srv.NetRestrict) } if err != nil { return err } + if err := ntab.SetFallbackNodes(srv.BootstrapNodesV5); err != nil { + return err + } + srv.DiscV5 = ntab } return nil } @@ -671,6 +671,7 @@ func (srv *Server) maxInboundConns() int { } func (srv *Server) maxDialedConns() (limit int) { + log.Info("max dialled", "no-dial", srv.NoDial, "max-peers", srv.MaxPeers) if srv.NoDial || srv.MaxPeers == 0 { return 0 } @@ -780,6 +781,7 @@ running: c.cont <- srv.postHandshakeChecks(peers, inboundCount, c) case c := <-srv.checkpointAddPeer: + log.Info("checkpoing add peer") // At this point the connection is past the protocol handshake. // Its capabilities are known and the remote identity is verified. err := srv.addPeerChecks(peers, inboundCount, c) @@ -1043,6 +1045,7 @@ func (srv *Server) checkpoint(c *conn, stage chan<- *conn) error { } func (srv *Server) launchPeer(c *conn) *Peer { + log.Info("launching peer") p := newPeer(srv.log, c, srv.Protocols) if srv.EnableMsgEvents { // If message events are enabled, pass the peerFeed @@ -1055,6 +1058,7 @@ func (srv *Server) launchPeer(c *conn) *Peer { // runPeer runs in its own goroutine for each peer. func (srv *Server) runPeer(p *Peer) { + log.Info("Running peer", "peer", p) if srv.newPeerHook != nil { srv.newPeerHook(p) } diff --git a/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go b/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go index 1610ea819..8c929ecdd 100644 --- a/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go +++ b/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go @@ -73,24 +73,6 @@ var CalaverasBootnodes = []string{ "enode://9e1096aa59862a6f164994cb5cb16f5124d6c992cdbf4535ff7dea43ea1512afe5448dca9df1b7ab0726129603f1a3336b631e4d7a1a44c94daddd03241587f9@3.9.20.133:30303", } -var V5Bootnodes = []string{ - // Teku team's bootnode - "enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA", - "enr:-KG4QDyytgmE4f7AnvW-ZaUOIi9i79qX4JwjRAiXBZCU65wOfBu-3Nb5I7b_Rmg3KCOcZM_C3y5pg7EBU5XGrcLTduQEhGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQ2_DUbiXNlY3AyNTZrMaEDKnz_-ps3UUOfHWVYaskI5kWYO_vtYMGYCQRAR3gHDouDdGNwgiMog3VkcIIjKA", - // Prylab team's bootnodes - "enr:-Ku4QImhMc1z8yCiNJ1TyUxdcfNucje3BGwEHzodEZUan8PherEo4sF7pPHPSIB1NNuSg5fZy7qFsjmUKs2ea1Whi0EBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQOVphkDqal4QzPMksc5wnpuC3gvSC8AfbFOnZY_On34wIN1ZHCCIyg", - "enr:-Ku4QP2xDnEtUXIjzJ_DhlCRN9SN99RYQPJL92TMlSv7U5C1YnYLjwOQHgZIUXw6c-BvRg2Yc2QsZxxoS_pPRVe0yK8Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMeFF5GrS7UZpAH2Ly84aLK-TyvH-dRo0JM1i8yygH50YN1ZHCCJxA", - "enr:-Ku4QPp9z1W4tAO8Ber_NQierYaOStqhDqQdOPY3bB3jDgkjcbk6YrEnVYIiCBbTxuar3CzS528d2iE7TdJsrL-dEKoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMw5fqqkw2hHC4F5HZZDPsNmPdB1Gi8JPQK7pRc9XHh-oN1ZHCCKvg", - // Lighthouse team's bootnodes - "enr:-IS4QLkKqDMy_ExrpOEWa59NiClemOnor-krjp4qoeZwIw2QduPC-q7Kz4u1IOWf3DDbdxqQIgC4fejavBOuUPy-HE4BgmlkgnY0gmlwhCLzAHqJc2VjcDI1NmsxoQLQSJfEAHZApkm5edTCZ_4qps_1k_ub2CxHFxi-gr2JMIN1ZHCCIyg", - "enr:-IS4QDAyibHCzYZmIYZCjXwU9BqpotWmv2BsFlIq1V31BwDDMJPFEbox1ijT5c2Ou3kvieOKejxuaCqIcjxBjJ_3j_cBgmlkgnY0gmlwhAMaHiCJc2VjcDI1NmsxoQJIdpj_foZ02MXz4It8xKD7yUHTBx7lVFn3oeRP21KRV4N1ZHCCIyg", - // EF bootnodes - "enr:-Ku4QHqVeJ8PPICcWk1vSn_XcSkjOkNiTg6Fmii5j6vUQgvzMc9L1goFnLKgXqBJspJjIsB91LTOleFmyWWrFVATGngBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhAMRHkWJc2VjcDI1NmsxoQKLVXFOhp2uX6jeT0DvvDpPcU8FWMjQdR4wMuORMhpX24N1ZHCCIyg", - "enr:-Ku4QG-2_Md3sZIAUebGYT6g0SMskIml77l6yR-M_JXc-UdNHCmHQeOiMLbylPejyJsdAPsTHJyjJB2sYGDLe0dn8uYBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhBLY-NyJc2VjcDI1NmsxoQORcM6e19T1T9gi7jxEZjk_sjVLGFscUNqAY9obgZaxbIN1ZHCCIyg", - "enr:-Ku4QPn5eVhcoF1opaFEvg1b6JNFD2rqVkHQ8HApOKK61OIcIXD127bKWgAtbwI7pnxx6cDyk_nI88TrZKQaGMZj0q0Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDayLMaJc2VjcDI1NmsxoQK2sBOLGcUb4AwuYzFuAVCaNHA-dy24UuEKkeFNgCVCsIN1ZHCCIyg", - "enr:-Ku4QEWzdnVtXc2Q0ZVigfCGggOVB2Vc1ZCPEc6j21NIFLODSJbvNaef1g4PxhPwl_3kax86YPheFUSLXPRs98vvYsoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDZBrP2Jc2VjcDI1NmsxoQM6jr8Rb1ktLEsVcKAPa08wCsKUmvoQ8khiOl_SLozf9IN1ZHCCIyg", -} - const dnsPrefix = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@" // KnownDNSNetwork returns the address of a public DNS-based node list for the given diff --git a/waku/waku.go b/waku/waku.go index 6fce25e46..e66724b3f 100644 --- a/waku/waku.go +++ b/waku/waku.go @@ -1056,7 +1056,7 @@ func (w *Waku) Send(envelope *common.Envelope) error { // Start implements node.Service, starting the background data propagation thread // of the Waku protocol. -func (w *Waku) Start(*p2p.Server) error { +func (w *Waku) Start() error { go w.update() numCPU := runtime.NumCPU() @@ -1519,6 +1519,10 @@ func (w *Waku) GetEnvelope(hash gethcommon.Hash) *common.Envelope { return w.envelopes[hash] } +func (w *Waku) Version() uint { + return 1 +} + // isEnvelopeCached checks if envelope with specific hash has already been received and cached. func (w *Waku) IsEnvelopeCached(hash gethcommon.Hash) bool { w.poolMu.Lock() diff --git a/wakuv2/waku.go b/wakuv2/waku.go index 5e2ea4a9d..5e4c41f27 100644 --- a/wakuv2/waku.go +++ b/wakuv2/waku.go @@ -548,7 +548,7 @@ func (w *Waku) Query(topics []types.TopicType, from uint64, to uint64, opts []st // Start implements node.Service, starting the background data propagation thread // of the Waku protocol. -func (w *Waku) Start(*p2p.Server) error { +func (w *Waku) Start() error { numCPU := runtime.NumCPU() for i := 0; i < numCPU; i++ { go w.processQueue()