diff --git a/app/client/cli/cmd.go b/app/client/cli/cmd.go index f9632cd0c..3df36108f 100644 --- a/app/client/cli/cmd.go +++ b/app/client/cli/cmd.go @@ -8,7 +8,7 @@ import ( "github.com/spf13/viper" "github.com/pokt-network/pocket/app/client/cli/flags" - "github.com/pokt-network/pocket/runtime/configs" + "github.com/pokt-network/pocket/app/client/cli/peer" "github.com/pokt-network/pocket/runtime/defaults" ) @@ -17,8 +17,6 @@ const ( flagBindErrFormat = "could not bind flag %q: %v" ) -var cfg *configs.Config - func init() { rootCmd.PersistentFlags().StringVar(&flags.RemoteCLIURL, "remote_cli_url", defaults.DefaultRemoteCLIURL, "takes a remote endpoint in the form of ://: (uses RPC Port)") // ensure that this flag can be overridden by the respective viper-conventional environment variable (i.e. `POCKET_REMOTE_CLI_URL`) @@ -39,19 +37,17 @@ func init() { if err := viper.BindPFlag("verbose", rootCmd.PersistentFlags().Lookup("verbose")); err != nil { log.Fatalf(flagBindErrFormat, "verbose", err) } + + // Add subdir commands + // DISCUSS: Should we put the peer commands as the other commands are so we dont have to do this? + rootCmd.AddCommand(peer.NewPeerCommand()) } var rootCmd = &cobra.Command{ - Use: cliExecutableName, - Short: "Pocket Network Command Line Interface (CLI)", - Long: "The CLI is meant to be an user but also a machine friendly way for interacting with Pocket Network.", - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - // by this time, the config path should be set - cfg = configs.ParseConfig(flags.ConfigPath) - // set final `remote_cli_url` value; order of precedence: flag > env var > config > default - flags.RemoteCLIURL = viper.GetString("remote_cli_url") - return nil - }, + Use: cliExecutableName, + Short: "Pocket Network Command Line Interface (CLI)", + Long: "The CLI is meant to be an user but also a machine friendly way for interacting with Pocket Network.", + PersistentPreRunE: flags.ParseConfigAndFlags, } func ExecuteContext(ctx context.Context) error { diff --git a/app/client/cli/flags/config.go b/app/client/cli/flags/config.go new file mode 100644 index 000000000..0de55a7aa --- /dev/null +++ b/app/client/cli/flags/config.go @@ -0,0 +1,19 @@ +package flags + +import ( + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "github.com/pokt-network/pocket/runtime/configs" +) + +var Cfg *configs.Config + +func ParseConfigAndFlags(_ *cobra.Command, _ []string) error { + // by this time, the config path should be set + Cfg = configs.ParseConfig(ConfigPath) + + // set final `remote_cli_url` value; order of precedence: flag > env var > config > default + RemoteCLIURL = viper.GetString("remote_cli_url") + return nil +} diff --git a/app/client/cli/helpers/common.go b/app/client/cli/helpers/common.go index 647d4241d..320eb7567 100644 --- a/app/client/cli/helpers/common.go +++ b/app/client/cli/helpers/common.go @@ -23,15 +23,14 @@ func FetchPeerstore(cmd *cobra.Command) (types.Peerstore, error) { if err != nil { return nil, err } - // TECHDEBT(#811): use `bus.GetPeerstoreProvider()` after peerstore provider - // is retrievable as a proper submodule - pstoreProvider, err := bus.GetModulesRegistry().GetModule(peerstore_provider.PeerstoreProviderSubmoduleName) + // TECHDEBT(#811): Remove type casting once Peerstore is available as a submodule + pstoreProvider, err := peerstore_provider.GetPeerstoreProvider(bus) if err != nil { - return nil, errors.New("retrieving peerstore provider") + return nil, err } currentHeightProvider := bus.GetCurrentHeightProvider() height := currentHeightProvider.CurrentHeight() - pstore, err := pstoreProvider.(peerstore_provider.PeerstoreProvider).GetStakedPeerstoreAtHeight(height) + pstore, err := pstoreProvider.GetStakedPeerstoreAtHeight(height) if err != nil { return nil, fmt.Errorf("retrieving peerstore at height %d", height) } diff --git a/app/client/cli/peer/list.go b/app/client/cli/peer/list.go new file mode 100644 index 000000000..b8cbe03eb --- /dev/null +++ b/app/client/cli/peer/list.go @@ -0,0 +1,97 @@ +package peer + +import ( + "fmt" + + "github.com/spf13/cobra" + "google.golang.org/protobuf/types/known/anypb" + + "github.com/pokt-network/pocket/app/client/cli/helpers" + "github.com/pokt-network/pocket/logger" + "github.com/pokt-network/pocket/p2p/debug" + "github.com/pokt-network/pocket/shared/messaging" +) + +var ErrRouterType = fmt.Errorf("must specify one of --staked, --unstaked, or --all") + +func NewListCommand() *cobra.Command { + return &cobra.Command{ + Use: "List", + Short: "List the known peers", + Long: "Prints a table of the Peer ID, Pokt Address and Service URL of the known peers", + Aliases: []string{"list", "ls"}, + RunE: listRunE, + } +} + +func listRunE(cmd *cobra.Command, _ []string) error { + var routerType debug.RouterType + + bus, err := helpers.GetBusFromCmd(cmd) + if err != nil { + return err + } + + switch { + case stakedFlag && !unstakedFlag && !allFlag: + routerType = debug.StakedRouterType + case unstakedFlag && !stakedFlag && !allFlag: + routerType = debug.UnstakedRouterType + case stakedFlag || unstakedFlag: + return ErrRouterType + // even if `allFlag` is false, we still want to print all connections + default: + routerType = debug.AllRouterTypes + } + + debugMsg := &messaging.DebugMessage{ + Action: messaging.DebugMessageAction_DEBUG_P2P_PRINT_PEER_LIST, + Type: messaging.DebugMessageRoutingType_DEBUG_MESSAGE_TYPE_BROADCAST, + Message: &anypb.Any{ + Value: []byte(routerType), + }, + } + debugMsgAny, err := anypb.New(debugMsg) + if err != nil { + return fmt.Errorf("error creating anypb from debug message: %w", err) + } + + if localFlag { + if err := debug.PrintPeerList(bus, routerType); err != nil { + return fmt.Errorf("error printing peer list: %w", err) + } + return nil + } + + // TECHDEBT(#811): will need to wait for DHT bootstrapping to complete before + // p2p broadcast can be used with to reach unstaked actors. + // CONSIDERATION: add the peer commands to the interactive CLI as the P2P module + // instance could persist between commands. Other interactive CLI commands which + // rely on unstaked actor router broadcast are working as expected. + + // TECHDEBT(#811): use broadcast instead to reach all peers. + return sendToStakedPeers(cmd, debugMsgAny) +} + +func sendToStakedPeers(cmd *cobra.Command, debugMsgAny *anypb.Any) error { + bus, err := helpers.GetBusFromCmd(cmd) + if err != nil { + return err + } + + pstore, err := helpers.FetchPeerstore(cmd) + if err != nil { + logger.Global.Fatal().Err(err).Msg("unable to retrieve the pstore") + } + + if pstore.Size() == 0 { + logger.Global.Fatal().Msg("no validators found") + } + + for _, peer := range pstore.GetPeerList() { + if err := bus.GetP2PModule().Send(peer.GetAddress(), debugMsgAny); err != nil { + logger.Global.Error().Err(err).Msg("failed to send debug message") + } + } + return nil +} diff --git a/app/client/cli/peer/peer.go b/app/client/cli/peer/peer.go new file mode 100644 index 000000000..e5fc01bfe --- /dev/null +++ b/app/client/cli/peer/peer.go @@ -0,0 +1,55 @@ +package peer + +import ( + "github.com/spf13/cobra" + + "github.com/pokt-network/pocket/app/client/cli/helpers" +) + +var allFlag, + stakedFlag, + unstakedFlag, + localFlag bool + +func NewPeerCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "Peer", + Short: "Manage peers", + Aliases: []string{"peer"}, + PersistentPreRunE: helpers.P2PDependenciesPreRunE, + } + + cmd.PersistentFlags(). + BoolVarP( + &allFlag, + "all", "a", + false, + "operations apply to both staked & unstaked router peerstores (default)", + ) + cmd.PersistentFlags(). + BoolVarP( + &stakedFlag, + "staked", "s", + false, + "operations only apply to staked router peerstore (i.e. raintree)", + ) + cmd.PersistentFlags(). + BoolVarP( + &unstakedFlag, + "unstaked", "u", + false, + "operations only apply to unstaked (including staked as a subset) router peerstore (i.e. gossipsub)", + ) + cmd.PersistentFlags(). + BoolVarP( + &localFlag, + "local", "l", + false, + "operations apply to the local (CLI binary's) P2P module instead of being broadcast", + ) + + // Add subcommands + cmd.AddCommand(NewListCommand()) + + return cmd +} diff --git a/app/client/cli/utils.go b/app/client/cli/utils.go index 2e3e0263e..36a7229e6 100644 --- a/app/client/cli/utils.go +++ b/app/client/cli/utils.go @@ -311,7 +311,7 @@ func attachKeybaseFlagsToSubcommands() []cmdOption { } func keybaseForCLI() (keybase.Keybase, error) { - return keybase.NewKeybase(cfg.Keybase) + return keybase.NewKeybase(flags.Cfg.Keybase) } func unableToConnectToRpc(err error) error { diff --git a/charts/pocket/README.md b/charts/pocket/README.md index 35993ddfd..b4aca5b9d 100644 --- a/charts/pocket/README.md +++ b/charts/pocket/README.md @@ -46,6 +46,7 @@ privateKeySecretKeyRef: | config.fisherman.enabled | bool | `false` | | | config.logger.format | string | `"json"` | | | config.logger.level | string | `"debug"` | | +| config.p2p.enable_peer_discovery_debug_rpc | bool | `false` | | | config.p2p.hostname | string | `""` | | | config.p2p.is_empty_connection_type | bool | `false` | | | config.p2p.max_mempool_count | int | `100000` | | diff --git a/charts/pocket/templates/statefulset.yaml b/charts/pocket/templates/statefulset.yaml index 4be68b50b..39eaa7d9c 100644 --- a/charts/pocket/templates/statefulset.yaml +++ b/charts/pocket/templates/statefulset.yaml @@ -100,10 +100,12 @@ spec: valueFrom: fieldRef: fieldPath: status.podIP - livenessProbe: - httpGet: - path: /v1/health - port: rpc + - name: POCKET_P2P_ENABLE_PEER_DISCOVERY_DEBUG_RPC + value: "true" +# livenessProbe: +# httpGet: +# path: /v1/health +# port: rpc readinessProbe: httpGet: path: /v1/health diff --git a/charts/pocket/values.yaml b/charts/pocket/values.yaml index 01d42b52e..afa383c2f 100644 --- a/charts/pocket/values.yaml +++ b/charts/pocket/values.yaml @@ -101,6 +101,7 @@ config: is_empty_connection_type: false private_key: "" # @ignored This value is needed but ignored - use privateKeySecretKeyRef instead max_mempool_count: 100000 + enable_peer_discovery_debug_rpc: false telemetry: enabled: true address: 0.0.0.0:9000 diff --git a/p2p/background/router.go b/p2p/background/router.go index 7899f7817..35fd002ce 100644 --- a/p2p/background/router.go +++ b/p2p/background/router.go @@ -17,7 +17,6 @@ import ( "github.com/pokt-network/pocket/logger" "github.com/pokt-network/pocket/p2p/config" "github.com/pokt-network/pocket/p2p/protocol" - "github.com/pokt-network/pocket/p2p/providers" "github.com/pokt-network/pocket/p2p/providers/peerstore_provider" typesP2P "github.com/pokt-network/pocket/p2p/types" "github.com/pokt-network/pocket/p2p/unicast" @@ -73,7 +72,7 @@ type backgroundRouter struct { subscription *pubsub.Subscription // kadDHT is a kademlia distributed hash table used for routing and peer discovery. kadDHT *dht.IpfsDHT - // TECHDEBT: `pstore` will likely be removed in future refactoring / simplification + // TECHDEBT(#747, #749): `pstore` will likely be removed in future refactoring / simplification // of the `Router` interface. // pstore is the background router's peerstore. Assigned in `backgroundRouter#setupPeerstore()`. pstore typesP2P.Peerstore @@ -258,18 +257,11 @@ func (rtr *backgroundRouter) setupDependencies(ctx context.Context, _ *config.Ba } func (rtr *backgroundRouter) setupPeerstore(ctx context.Context) (err error) { - rtr.logger.Warn().Msg("setting up peerstore...") - - // TECHDEBT(#810, #811): use `bus.GetPeerstoreProvider()` after peerstore provider + // TECHDEBT(#811): use `bus.GetPeerstoreProvider()` after peerstore provider // is retrievable as a proper submodule - pstoreProviderModule, err := rtr.GetBus().GetModulesRegistry(). - GetModule(peerstore_provider.PeerstoreProviderSubmoduleName) + pstoreProvider, err := peerstore_provider.GetPeerstoreProvider(rtr.GetBus()) if err != nil { - return fmt.Errorf("retrieving peerstore provider: %w", err) - } - pstoreProvider, ok := pstoreProviderModule.(providers.PeerstoreProvider) - if !ok { - return fmt.Errorf("unexpected peerstore provider type: %T", pstoreProviderModule) + return err } rtr.logger.Debug().Msg("setupCurrentHeightProvider") @@ -284,10 +276,7 @@ func (rtr *backgroundRouter) setupPeerstore(ctx context.Context) (err error) { } // TECHDEBT(#859): integrate with `p2pModule#bootstrap()`. - if err := rtr.bootstrap(ctx); err != nil { - return fmt.Errorf("bootstrapping peerstore: %w", err) - } - + rtr.bootstrap(ctx) return nil } @@ -343,33 +332,38 @@ func (rtr *backgroundRouter) setupSubscription() (err error) { } // TECHDEBT(#859): integrate with `p2pModule#bootstrap()`. -func (rtr *backgroundRouter) bootstrap(ctx context.Context) error { +func (rtr *backgroundRouter) bootstrap(ctx context.Context) { // CONSIDERATION: add `GetPeers` method, which returns a map, // to the `PeerstoreProvider` interface to simplify this loop. - for _, peer := range rtr.pstore.GetPeerList() { + peerList := rtr.pstore.GetPeerList() + for _, peer := range peerList { if err := utils.AddPeerToLibp2pHost(rtr.host, peer); err != nil { - return err + rtr.logger.Error().Err(err).Msg("error adding peer to libp2p host") + continue } libp2pAddrInfo, err := utils.Libp2pAddrInfoFromPeer(peer) if err != nil { - return fmt.Errorf( - "converting peer info, pokt address: %s: %w", - peer.GetAddress(), - err, - ) + rtr.logger.Error().Err(err).Msg("error converting peer info") + continue } // don't attempt to connect to self if rtr.host.ID() == libp2pAddrInfo.ID { - return nil + rtr.logger.Debug().Msg("not bootstrapping against self") + continue } + rtr.logger.Debug().Fields(map[string]any{ + "peer_id": libp2pAddrInfo.ID.String(), + "peer_addr": libp2pAddrInfo.Addrs[0].String(), + "num_peers": len(peerList) - 1, // -1 as includes self + }).Msg("connecting to peer") if err := rtr.connectWithRetry(ctx, libp2pAddrInfo); err != nil { - return fmt.Errorf("connecting to peer: %w", err) + rtr.logger.Error().Err(err).Msg("error connecting to bootstrap peer") + continue } } - return nil } // connectWithRetry attempts to connect to the given peer, retrying up to connectMaxRetries times @@ -382,11 +376,11 @@ func (rtr *backgroundRouter) connectWithRetry(ctx context.Context, libp2pAddrInf return nil } - fmt.Printf("Failed to connect (attempt %d), retrying in %v...\n", i+1, connectRetryTimeout) + rtr.logger.Error().Msgf("failed to connect (attempt %d), retrying in %v...", i+1, connectRetryTimeout) time.Sleep(connectRetryTimeout) } - return fmt.Errorf("failed to connect after %d attempts, last error: %w", 5, err) + return fmt.Errorf("failed to connect after %d attempts, last error: %w", connectMaxRetries, err) } // topicValidator is used in conjunction with libp2p-pubsub's notion of "topic @@ -430,7 +424,6 @@ func (rtr *backgroundRouter) readSubscription(ctx context.Context) { return } msg, err := rtr.subscription.Next(ctx) - if err != nil { rtr.logger.Error().Err(err). Msg("error reading from background topic subscription") diff --git a/p2p/background/router_test.go b/p2p/background/router_test.go index 5d5224c86..ef03e6cd7 100644 --- a/p2p/background/router_test.go +++ b/p2p/background/router_test.go @@ -311,9 +311,9 @@ func TestBackgroundRouter_Broadcast(t *testing.T) { // This test should be redesigned using atomic counters or // something similar to avoid this issue. defer func() { - if err := recover(); err != nil { - if err.(error).Error() == "sync: negative WaitGroup counter" { - // ignore negative WaitGroup counter error + if rcv := recover(); err != nil { + // ignore negative WaitGroup counter error + if msg, ok := rcv.(string); ok && msg == "sync: negative WaitGroup counter" { return } // fail the test for anything else; converting the panic into @@ -380,18 +380,13 @@ func bootstrap(t *testing.T, ctx context.Context, testHosts []libp2pHost.Host) { continue } - p2pAddr, err := multiaddr.NewMultiaddr(fmt.Sprintf("/p2p/%s", bootstrapHost.ID())) - require.NoError(t, err) - addrInfo := libp2pPeer.AddrInfo{ - ID: bootstrapHost.ID(), - Addrs: []multiaddr.Multiaddr{ - bootstrapAddr.Encapsulate(p2pAddr), - }, + ID: bootstrapHost.ID(), + Addrs: []multiaddr.Multiaddr{bootstrapAddr}, } t.Logf("connecting to %s...", addrInfo.ID.String()) - err = h.Connect(ctx, addrInfo) + err := h.Connect(ctx, addrInfo) require.NoError(t, err) } } diff --git a/p2p/bootstrap.go b/p2p/bootstrap.go index 258fb19a2..c74d34ad2 100644 --- a/p2p/bootstrap.go +++ b/p2p/bootstrap.go @@ -10,7 +10,7 @@ import ( "strings" rpcCHP "github.com/pokt-network/pocket/p2p/providers/current_height_provider/rpc" - rpcABP "github.com/pokt-network/pocket/p2p/providers/peerstore_provider/rpc" + rpcPSP "github.com/pokt-network/pocket/p2p/providers/peerstore_provider/rpc" typesP2P "github.com/pokt-network/pocket/p2p/types" "github.com/pokt-network/pocket/rpc" "github.com/pokt-network/pocket/runtime/defaults" @@ -59,9 +59,9 @@ func (m *p2pModule) bootstrap() error { continue } - pstoreProvider, err := rpcABP.Create( + pstoreProvider, err := rpcPSP.Create( m.GetBus(), - rpcABP.WithCustomRPCURL(bootstrapNode), + rpcPSP.WithCustomRPCURL(bootstrapNode), ) if err != nil { return fmt.Errorf("creating RPC peerstore provider: %w", err) @@ -81,20 +81,30 @@ func (m *p2pModule) bootstrap() error { m.logger.Warn().Err(err).Str("endpoint", bootstrapNode).Msg("Error getting address book from bootstrap node") continue } - } - for _, peer := range pstore.GetPeerList() { - m.logger.Debug().Str("address", peer.GetAddress().String()).Msg("Adding peer to router") - if err := m.stakedActorRouter.AddPeer(peer); err != nil { - m.logger.Error().Err(err). - Str("pokt_address", peer.GetAddress().String()). - Msg("adding peer") + for _, peer := range pstore.GetPeerList() { + m.logger.Debug().Str("address", peer.GetAddress().String()).Msg("Adding peer to router") + isStaked, err := m.isStakedActor() + if err != nil { + m.logger.Error().Err(err).Msg("checking if node is staked") + } + if isStaked { + if err := m.stakedActorRouter.AddPeer(peer); err != nil { + m.logger.Error().Err(err). + Str("pokt_address", peer.GetAddress().String()). + Msg("adding peer to staked actor router") + } + } + + if err := m.unstakedActorRouter.AddPeer(peer); err != nil { + m.logger.Error().Err(err). + Str("pokt_address", peer.GetAddress().String()). + Msg("adding peer to unstaked actor router") + } } } - if m.stakedActorRouter.GetPeerstore().Size() == 0 { - return fmt.Errorf("bootstrap failed") - } + // TECHDEBT(#859): determine bootstrapping success/error conditions. return nil } diff --git a/p2p/debug.go b/p2p/debug.go new file mode 100644 index 000000000..1361de5c4 --- /dev/null +++ b/p2p/debug.go @@ -0,0 +1,22 @@ +package p2p + +import ( + "fmt" + + "github.com/pokt-network/pocket/p2p/debug" + typesP2P "github.com/pokt-network/pocket/p2p/types" + "github.com/pokt-network/pocket/shared/messaging" +) + +func (m *p2pModule) handleDebugMessage(msg *messaging.DebugMessage) error { + switch msg.Action { + case messaging.DebugMessageAction_DEBUG_P2P_PRINT_PEER_LIST: + if !m.cfg.EnablePeerDiscoveryDebugRpc { + return typesP2P.ErrPeerDiscoveryDebugRPCDisabled + } + routerType := debug.RouterType(msg.Message.Value) + return debug.PrintPeerList(m.GetBus(), routerType) + default: + return fmt.Errorf("unsupported P2P debug message action: %s", msg.Action) + } +} diff --git a/p2p/debug/list.go b/p2p/debug/list.go new file mode 100644 index 000000000..5ba9e8c25 --- /dev/null +++ b/p2p/debug/list.go @@ -0,0 +1,130 @@ +package debug + +import ( + "fmt" + "os" + + "github.com/pokt-network/pocket/p2p/providers/peerstore_provider" + "github.com/pokt-network/pocket/p2p/types" + "github.com/pokt-network/pocket/p2p/utils" + "github.com/pokt-network/pocket/shared/modules" +) + +var peerListTableHeader = []string{"Peer ID", "Pokt Address", "ServiceURL"} + +// PrintPeerList retrieves the correct peer list using the peerstore provider +// on the bus and then passes this list to PrintPeerListTable to print the +// list of peers to os.Stdout as a table +func PrintPeerList(bus modules.Bus, routerType RouterType) error { + var ( + peers types.PeerList + routerPlurality = "" + ) + + // TECHDEBT(#811): use `bus.GetPeerstoreProvider()` after peerstore provider + // is retrievable as a proper submodule. + pstoreProvider, err := peerstore_provider.GetPeerstoreProvider(bus) + if err != nil { + return err + } + + switch routerType { + case StakedRouterType: + // TODO_IN_THIS_COMMIT: what about unstaked peers actors? + // if !isStaked ... + pstore, err := pstoreProvider.GetStakedPeerstoreAtCurrentHeight() + if err != nil { + return fmt.Errorf("error getting staked peerstore: %v", err) + } + + peers = pstore.GetPeerList() + case UnstakedRouterType: + pstore, err := pstoreProvider.GetUnstakedPeerstore() + if err != nil { + return fmt.Errorf("error getting unstaked peerstore: %v", err) + } + + peers = pstore.GetPeerList() + case AllRouterTypes: + routerPlurality = "s" + + // TODO_IN_THIS_COMMIT: what about unstaked peers actors? + // if !isStaked ... + stakedPStore, err := pstoreProvider.GetStakedPeerstoreAtCurrentHeight() + if err != nil { + return fmt.Errorf("error getting staked peerstore: %v", err) + } + unstakedPStore, err := pstoreProvider.GetUnstakedPeerstore() + if err != nil { + return fmt.Errorf("error getting unstaked peerstore: %v", err) + } + + unstakedPeers := unstakedPStore.GetPeerList() + stakedPeers := stakedPStore.GetPeerList() + additionalPeers, _ := unstakedPeers.Delta(stakedPeers) + + // NB: there should never be any "additional" peers. This would represent + // a staked actor who is not participating in background gossip for some + // reason. It's possible that a staked actor node which has restarted + // recently and hasn't yet completed background router bootstrapping may + // result in peers experiencing this state. + if len(additionalPeers) == 0 { + return PrintPeerListTable(unstakedPeers) + } + + allPeers := append(types.PeerList{}, unstakedPeers...) + allPeers = append(allPeers, additionalPeers...) + peers = allPeers + default: + return fmt.Errorf("unsupported router type: %s", routerType) + } + + if err := LogSelfAddress(bus); err != nil { + return fmt.Errorf("error printing self address: %w", err) + } + + // NB: Intentionally printing with `fmt` instead of the logger to match + // `utils.PrintPeerListTable` which does not use the logger due to + // incompatibilities with the tabwriter. + // (This doesn't seem to work as expected; i.e. not printing at all in tilt.) + if _, err := fmt.Fprintf( + os.Stdout, + "%s router peerstore%s:\n", + routerType, + routerPlurality, + ); err != nil { + return fmt.Errorf("error printing to stdout: %w", err) + } + + if err := PrintPeerListTable(peers); err != nil { + return fmt.Errorf("error printing peer list: %w", err) + } + return nil +} + +// PrintPeerListTable prints a table of the passed peers to stdout. Header row is defined +// by `peerListTableHeader`. Row printing behavior is defined by `peerListRowConsumerFactory`. +func PrintPeerListTable(peers types.PeerList) error { + return utils.PrintTable(peerListTableHeader, peerListRowConsumerFactory(peers)) +} + +func peerListRowConsumerFactory(peers types.PeerList) utils.RowConsumer { + return func(provideRow utils.RowProvider) error { + for _, peer := range peers { + libp2pAddrInfo, err := utils.Libp2pAddrInfoFromPeer(peer) + if err != nil { + return fmt.Errorf("error converting peer to libp2p addr info: %w", err) + } + + err = provideRow( + libp2pAddrInfo.ID.String(), + peer.GetAddress().String(), + peer.GetServiceURL(), + ) + if err != nil { + return err + } + } + return nil + } +} diff --git a/p2p/debug/peers.go b/p2p/debug/peers.go new file mode 100644 index 000000000..60f206b00 --- /dev/null +++ b/p2p/debug/peers.go @@ -0,0 +1,31 @@ +package debug + +import ( + "fmt" + "os" + + "github.com/pokt-network/pocket/shared/modules" +) + +type RouterType string + +const ( + StakedRouterType RouterType = "staked" + UnstakedRouterType RouterType = "unstaked" + AllRouterTypes RouterType = "all" +) + +func LogSelfAddress(bus modules.Bus) error { + p2pModule := bus.GetP2PModule() + if p2pModule == nil { + return fmt.Errorf("no p2p module found on the bus") + } + + selfAddr, err := p2pModule.GetAddress() + if err != nil { + return fmt.Errorf("getting self address: %w", err) + } + + _, err = fmt.Fprintf(os.Stdout, "self address: %s", selfAddr.String()) + return err +} diff --git a/p2p/event_handler.go b/p2p/event_handler.go index b1184e860..632adeddc 100644 --- a/p2p/event_handler.go +++ b/p2p/event_handler.go @@ -5,6 +5,7 @@ import ( "google.golang.org/protobuf/types/known/anypb" + "github.com/pokt-network/pocket/p2p/providers/peerstore_provider" "github.com/pokt-network/pocket/shared/codec" coreTypes "github.com/pokt-network/pocket/shared/core/types" "github.com/pokt-network/pocket/shared/messaging" @@ -31,7 +32,7 @@ func (m *p2pModule) HandleEvent(event *anypb.Any) error { } oldPeerList := m.stakedActorRouter.GetPeerstore().GetPeerList() - pstoreProvider, err := m.getPeerstoreProvider() + pstoreProvider, err := peerstore_provider.GetPeerstoreProvider(m.GetBus()) if err != nil { return err } @@ -62,21 +63,9 @@ func (m *p2pModule) HandleEvent(event *anypb.Any) error { m.logger.Debug().Fields(messaging.TransitionEventToMap(stateMachineTransitionEvent)).Msg("Received state machine transition event") if stateMachineTransitionEvent.NewState == string(coreTypes.StateMachineState_P2P_Bootstrapping) { - staked, err := m.isStakedActor() - if err != nil { + if err := m.bootstrap(); err != nil { return err } - if staked { - // TECHDEBT(#859): this will never happen as the peerstore is - // seeded from consensus during P2P module construction. - if m.stakedActorRouter.GetPeerstore().Size() == 0 { - m.logger.Warn().Msg("No peers in peerstore, bootstrapping") - - if err := m.bootstrap(); err != nil { - return err - } - } - } // TECHDEBT(#859): for unstaked actors, unstaked actor (background) // router bootstrapping SHOULD complete before the event below is sent. @@ -87,6 +76,13 @@ func (m *p2pModule) HandleEvent(event *anypb.Any) error { } } + case messaging.DebugMessageEventType: + debugMessage, ok := evt.(*messaging.DebugMessage) + if !ok { + return fmt.Errorf("unexpected DebugMessage type: %T", evt) + } + + return m.handleDebugMessage(debugMessage) default: return fmt.Errorf("unknown event type: %s", event.MessageName()) } diff --git a/p2p/module.go b/p2p/module.go index 6bb8f479a..b4d7eb86c 100644 --- a/p2p/module.go +++ b/p2p/module.go @@ -15,7 +15,6 @@ import ( "github.com/pokt-network/pocket/logger" "github.com/pokt-network/pocket/p2p/background" "github.com/pokt-network/pocket/p2p/config" - "github.com/pokt-network/pocket/p2p/providers" "github.com/pokt-network/pocket/p2p/providers/peerstore_provider" persPSP "github.com/pokt-network/pocket/p2p/providers/peerstore_provider/persistence" "github.com/pokt-network/pocket/p2p/raintree" @@ -291,12 +290,9 @@ func (m *p2pModule) setupDependencies() error { func (m *p2pModule) setupPeerstoreProvider() error { m.logger.Debug().Msg("setupPeerstoreProvider") - // TECHDEBT(#810, #811): use `bus.GetPeerstoreProvider()` after peerstore provider + // TECHDEBT(#811): use `bus.GetPeerstoreProvider()` after peerstore provider // is retrievable as a proper submodule - pstoreProviderModule, err := m.GetBus(). - GetModulesRegistry(). - GetModule(peerstore_provider.PeerstoreProviderSubmoduleName) - if err != nil { + if _, err := peerstore_provider.GetPeerstoreProvider(m.GetBus()); err != nil { // TECHDEBT: compare against `runtime.ErrModuleNotRegistered(...)`. m.logger.Debug().Msg("creating new persistence peerstore...") // Ensure a peerstore provider exists by creating a `persistencePeerstoreProvider`. @@ -307,9 +303,6 @@ func (m *p2pModule) setupPeerstoreProvider() error { } m.logger.Debug().Msg("loaded peerstore provider...") - if _, ok := pstoreProviderModule.(providers.PeerstoreProvider); !ok { - return fmt.Errorf("unknown peerstore provider type: %T", pstoreProviderModule) - } return nil } @@ -517,7 +510,7 @@ func (m *p2pModule) getMultiaddr() (multiaddr.Multiaddr, error) { } func (m *p2pModule) getStakedPeerstore() (typesP2P.Peerstore, error) { - pstoreProvider, err := m.getPeerstoreProvider() + pstoreProvider, err := peerstore_provider.GetPeerstoreProvider(m.GetBus()) if err != nil { return nil, err } @@ -527,21 +520,6 @@ func (m *p2pModule) getStakedPeerstore() (typesP2P.Peerstore, error) { ) } -// TECHDEBT(#810, #811): replace with `bus.GetPeerstoreProvider()` once available. -func (m *p2pModule) getPeerstoreProvider() (peerstore_provider.PeerstoreProvider, error) { - pstoreProviderModule, err := m.GetBus(). - GetModulesRegistry(). - GetModule(peerstore_provider.PeerstoreProviderSubmoduleName) - if err != nil { - return nil, err - } - pstoreProvider, ok := pstoreProviderModule.(peerstore_provider.PeerstoreProvider) - if !ok { - return nil, fmt.Errorf("peerstore provider not available") - } - return pstoreProvider, nil -} - // isStakedActor returns whether the current node is a staked actor at the current height. // Return an error if a peerstore can't be provided. func (m *p2pModule) isStakedActor() (bool, error) { diff --git a/p2p/providers/peerstore_provider/peerstore_provider.go b/p2p/providers/peerstore_provider/peerstore_provider.go index bbf57746a..190625aab 100644 --- a/p2p/providers/peerstore_provider/peerstore_provider.go +++ b/p2p/providers/peerstore_provider/peerstore_provider.go @@ -3,6 +3,8 @@ package peerstore_provider //go:generate mockgen -package=mock_types -destination=../../types/mocks/peerstore_provider_mock.go github.com/pokt-network/pocket/p2p/providers/peerstore_provider PeerstoreProvider import ( + "fmt" + "github.com/pokt-network/pocket/logger" typesP2P "github.com/pokt-network/pocket/p2p/types" coreTypes "github.com/pokt-network/pocket/shared/core/types" @@ -21,6 +23,10 @@ type PeerstoreProvider interface { // at a given height. These peers communicate via the p2p module's staked actor // router. GetStakedPeerstoreAtHeight(height uint64) (typesP2P.Peerstore, error) + // GetStakedPeerstoreAtCurrentHeight returns a peerstore containing all staked + // peers at the current height. These peers communicate via the p2p module's + // staked actor router. + GetStakedPeerstoreAtCurrentHeight() (typesP2P.Peerstore, error) // GetUnstakedPeerstore returns a peerstore containing all peers which // communicate via the p2p module's unstaked actor router. GetUnstakedPeerstore() (typesP2P.Peerstore, error) @@ -60,3 +66,18 @@ func ActorToPeer(abp PeerstoreProvider, actor *coreTypes.Actor) (typesP2P.Peer, return peer, nil } + +// TECHDEBT(#811): use `bus.GetPeerstoreProvider()` after peerstore provider +// is retrievable as a proper submodule. +func GetPeerstoreProvider(bus modules.Bus) (PeerstoreProvider, error) { + pstoreProviderModule, err := bus.GetModulesRegistry(). + GetModule(PeerstoreProviderSubmoduleName) + if err != nil { + return nil, fmt.Errorf("getting peerstore provider: %w", err) + } + pstoreProvider, ok := pstoreProviderModule.(PeerstoreProvider) + if !ok { + return nil, fmt.Errorf("unknown peerstore provider type: %T", pstoreProviderModule) + } + return pstoreProvider, nil +} diff --git a/p2p/providers/peerstore_provider/persistence/provider.go b/p2p/providers/peerstore_provider/persistence/provider.go index cbd1ec82c..1b98bf0c6 100644 --- a/p2p/providers/peerstore_provider/persistence/provider.go +++ b/p2p/providers/peerstore_provider/persistence/provider.go @@ -1,6 +1,8 @@ package persistence import ( + "fmt" + "github.com/pokt-network/pocket/p2p/providers/peerstore_provider" typesP2P "github.com/pokt-network/pocket/p2p/types" "github.com/pokt-network/pocket/shared/modules" @@ -12,8 +14,10 @@ var ( _ persistencePStoreProviderFactory = &persistencePeerstoreProvider{} ) -type persistencePStoreProviderOption func(*persistencePeerstoreProvider) -type persistencePStoreProviderFactory = modules.FactoryWithOptions[peerstore_provider.PeerstoreProvider, persistencePStoreProviderOption] +type ( + persistencePStoreProviderOption func(*persistencePeerstoreProvider) + persistencePStoreProviderFactory = modules.FactoryWithOptions[peerstore_provider.PeerstoreProvider, persistencePStoreProviderOption] +) type persistencePeerstoreProvider struct { base_modules.IntegrableModule @@ -56,7 +60,23 @@ func (persistencePSP *persistencePeerstoreProvider) GetStakedPeerstoreAtHeight(h return peerstore_provider.ActorsToPeerstore(persistencePSP, validators) } +func (persistencePSP *persistencePeerstoreProvider) GetStakedPeerstoreAtCurrentHeight() (typesP2P.Peerstore, error) { + currentHeight := persistencePSP.GetBus().GetCurrentHeightProvider().CurrentHeight() + return persistencePSP.GetStakedPeerstoreAtHeight(currentHeight) +} + // GetStakedPeerstoreAtHeight implements the respective `PeerstoreProvider` interface method. func (persistencePSP *persistencePeerstoreProvider) GetUnstakedPeerstore() (typesP2P.Peerstore, error) { - return peerstore_provider.GetUnstakedPeerstore(persistencePSP.GetBus()) + // TECHDEBT(#810, #811): use `bus.GetUnstakedActorRouter()` once it's available. + unstakedActorRouterMod, err := persistencePSP.GetBus().GetModulesRegistry().GetModule(typesP2P.UnstakedActorRouterSubmoduleName) + if err != nil { + return nil, err + } + + unstakedActorRouter, ok := unstakedActorRouterMod.(typesP2P.Router) + if !ok { + return nil, fmt.Errorf("unexpected unstaked actor router submodule type: %T", unstakedActorRouterMod) + } + + return unstakedActorRouter.GetPeerstore(), nil } diff --git a/p2p/providers/peerstore_provider/rpc/provider.go b/p2p/providers/peerstore_provider/rpc/provider.go index b0da88f69..56d650e1f 100644 --- a/p2p/providers/peerstore_provider/rpc/provider.go +++ b/p2p/providers/peerstore_provider/rpc/provider.go @@ -21,8 +21,10 @@ var ( _ rpcPeerstoreProviderFactory = &rpcPeerstoreProvider{} ) -type rpcPeerstoreProviderOption func(*rpcPeerstoreProvider) -type rpcPeerstoreProviderFactory = modules.FactoryWithOptions[peerstore_provider.PeerstoreProvider, rpcPeerstoreProviderOption] +type ( + rpcPeerstoreProviderOption func(*rpcPeerstoreProvider) + rpcPeerstoreProviderFactory = modules.FactoryWithOptions[peerstore_provider.PeerstoreProvider, rpcPeerstoreProviderOption] +) type rpcPeerstoreProvider struct { base_modules.IntegrableModule @@ -91,8 +93,24 @@ func (rpcPSP *rpcPeerstoreProvider) GetStakedPeerstoreAtHeight(height uint64) (t return peerstore_provider.ActorsToPeerstore(rpcPSP, coreActors) } +func (rpcPSP *rpcPeerstoreProvider) GetStakedPeerstoreAtCurrentHeight() (typesP2P.Peerstore, error) { + currentHeight := rpcPSP.GetBus().GetCurrentHeightProvider().CurrentHeight() + return rpcPSP.GetStakedPeerstoreAtHeight(currentHeight) +} + func (rpcPSP *rpcPeerstoreProvider) GetUnstakedPeerstore() (typesP2P.Peerstore, error) { - return peerstore_provider.GetUnstakedPeerstore(rpcPSP.GetBus()) + // TECHDEBT(#811): use `bus.GetUnstakedActorRouter()` once it's available. + unstakedActorRouterMod, err := rpcPSP.GetBus().GetModulesRegistry().GetModule(typesP2P.UnstakedActorRouterSubmoduleName) + if err != nil { + return nil, err + } + + unstakedActorRouter, ok := unstakedActorRouterMod.(typesP2P.Router) + if !ok { + return nil, fmt.Errorf("unexpected unstaked actor router submodule type: %T", unstakedActorRouterMod) + } + + return unstakedActorRouter.GetPeerstore(), nil } func (rpcPSP *rpcPeerstoreProvider) initRPCClient() { diff --git a/p2p/providers/peerstore_provider/unstaked.go b/p2p/providers/peerstore_provider/unstaked.go deleted file mode 100644 index b107922fe..000000000 --- a/p2p/providers/peerstore_provider/unstaked.go +++ /dev/null @@ -1,34 +0,0 @@ -package peerstore_provider - -import ( - "fmt" - - typesP2P "github.com/pokt-network/pocket/p2p/types" - "github.com/pokt-network/pocket/shared/modules" -) - -// unstakedPeerstoreProvider is an interface which the p2p module supports in -// order to allow access to the unstaked-actor-router's peerstore. -// -// NB: this peerstore includes all actors which participate in P2P (e.g. full -// and light clients but also validators, servicers, etc.). -// -// TECHDEBT(#811): will become unnecessary after `modules.P2PModule#GetUnstakedPeerstore` is added.` -// CONSIDERATION: split `PeerstoreProvider` into `StakedPeerstoreProvider` and `UnstakedPeerstoreProvider`. -// (see: https://github.com/pokt-network/pocket/pull/804#issuecomment-1576531916) -type unstakedPeerstoreProvider interface { - GetUnstakedPeerstore() (typesP2P.Peerstore, error) -} - -func GetUnstakedPeerstore(bus modules.Bus) (typesP2P.Peerstore, error) { - p2pModule := bus.GetP2PModule() - if p2pModule == nil { - return nil, fmt.Errorf("p2p module is not registered to bus and is required") - } - - unstakedPSP, ok := p2pModule.(unstakedPeerstoreProvider) - if !ok { - return nil, fmt.Errorf("p2p module does not implement unstakedPeerstoreProvider") - } - return unstakedPSP.GetUnstakedPeerstore() -} diff --git a/p2p/raintree/peerstore_utils.go b/p2p/raintree/peerstore_utils.go index aab31a5ba..e0fbf8a77 100644 --- a/p2p/raintree/peerstore_utils.go +++ b/p2p/raintree/peerstore_utils.go @@ -20,8 +20,8 @@ const ( func (rtr *rainTreeRouter) getPeerstoreSize(level uint32, height uint64) int { peersView, maxNumLevels := rtr.peersManager.getPeersViewWithLevels() - // TECHDEBT(#810, 811): use `bus.GetPeerstoreProvider()` instead once available. - pstoreProvider, err := rtr.getPeerstoreProvider() + // TECHDEBT(#811): use `bus.GetPeerstoreProvider()` instead once available. + pstoreProvider, err := peerstore_provider.GetPeerstoreProvider(rtr.GetBus()) if err != nil { // Should never happen; enforced by a `rtr.getPeerstoreProvider()` call // & error handling in `rtr.broadcastAtLevel()`. @@ -41,21 +41,6 @@ func (rtr *rainTreeRouter) getPeerstoreSize(level uint32, height uint64) int { return int(float64(len(peersView.GetAddrs())) * (shrinkageCoefficient)) } -// TECHDEBT(#810, 811): replace with `bus.GetPeerstoreProvider()` once available. -func (rtr *rainTreeRouter) getPeerstoreProvider() (peerstore_provider.PeerstoreProvider, error) { - pstoreProviderModule, err := rtr.GetBus().GetModulesRegistry(). - GetModule(peerstore_provider.PeerstoreProviderSubmoduleName) - if err != nil { - return nil, err - } - - pstoreProvider, ok := pstoreProviderModule.(peerstore_provider.PeerstoreProvider) - if !ok { - return nil, fmt.Errorf("unexpected peerstore provider module type: %T", pstoreProviderModule) - } - return pstoreProvider, nil -} - // getTargetsAtLevel returns the targets for a given level func (rtr *rainTreeRouter) getTargetsAtLevel(level uint32) []target { height := rtr.GetBus().GetCurrentHeightProvider().CurrentHeight() diff --git a/p2p/raintree/router.go b/p2p/raintree/router.go index 90ff95bc4..3d7b9b899 100644 --- a/p2p/raintree/router.go +++ b/p2p/raintree/router.go @@ -9,6 +9,7 @@ import ( "github.com/pokt-network/pocket/logger" "github.com/pokt-network/pocket/p2p/config" "github.com/pokt-network/pocket/p2p/protocol" + "github.com/pokt-network/pocket/p2p/providers/peerstore_provider" typesP2P "github.com/pokt-network/pocket/p2p/types" "github.com/pokt-network/pocket/p2p/unicast" "github.com/pokt-network/pocket/p2p/utils" @@ -67,7 +68,7 @@ func (*rainTreeRouter) Create( bus.RegisterModule(rtr) currentHeightProvider := bus.GetCurrentHeightProvider() - pstoreProvider, err := rtr.getPeerstoreProvider() + pstoreProvider, err := peerstore_provider.GetPeerstoreProvider(bus) if err != nil { return nil, err } @@ -122,10 +123,10 @@ func (rtr *rainTreeRouter) broadcastAtLevel(data []byte, level uint32) error { return err } - // TECHDEBT(#810, #811): remove once `bus.GetPeerstoreProvider()` is available. - // Pre-handling the error from `rtr.getPeerstoreProvider()` before it is called + // TECHDEBT(#811): remove once `bus.GetPeerstoreProvider()` is available. + // Pre-handling the error from `GetPeerstoreProvider()` before it is called // downstream in a context without an error return value. - if _, err = rtr.getPeerstoreProvider(); err != nil { + if _, err = peerstore_provider.GetPeerstoreProvider(rtr.GetBus()); err != nil { return err } diff --git a/p2p/types/errors.go b/p2p/types/errors.go index 8042ad775..3e225c304 100644 --- a/p2p/types/errors.go +++ b/p2p/types/errors.go @@ -6,8 +6,9 @@ import ( ) var ( - ErrUnknownPeer = errors.New("unknown peer") - ErrInvalidNonce = errors.New("invalid nonce") + ErrUnknownPeer = errors.New("unknown peer") + ErrInvalidNonce = errors.New("invalid nonce") + ErrPeerDiscoveryDebugRPCDisabled = errors.New("peer discovery debug RPC disabled") ) func ErrUnknownEventType(msg any) error { diff --git a/p2p/utils/logging.go b/p2p/utils/logging.go index ac999c62a..ea9a787c6 100644 --- a/p2p/utils/logging.go +++ b/p2p/utils/logging.go @@ -1,14 +1,27 @@ package utils import ( + "fmt" "net" + "os" + "text/tabwriter" "github.com/libp2p/go-libp2p/core/network" + "github.com/rs/zerolog" + "github.com/pokt-network/pocket/p2p/types" "github.com/pokt-network/pocket/shared/modules" - "github.com/rs/zerolog" ) +// RowProvider is a function which receives a variadic number of "column" values. +// It is intended to be passed to a `RowConsumer` so that the consumer can operate +// on the column values, row-by-row, without having to know how to produce them. +type RowProvider func(columns ...string) error + +// RowConsumer is any function which receives a `RowProvider` in order to consume +// its column values, row-by-row. +type RowConsumer func(RowProvider) error + type scopeCallback func(scope network.ResourceScope) error // LogScopeStatFactory returns a function which prints the given scope stat fields @@ -41,6 +54,63 @@ func LogIncomingMsg(logger *modules.Logger, hostname string, peer types.Peer) { logMessage(logger, msg, hostname, peer) } +// Print table prints a table to stdout. Header row is defined by `header`. Row printing +// behavior is defined by `consumeRows`. Header length SHOULD match row length. +func PrintTable(header []string, consumeRows RowConsumer) error { + w := new(tabwriter.Writer) + w.Init(os.Stdout, 0, 0, 1, ' ', 0) + + // Print header + for _, col := range header { + if _, err := fmt.Fprintf(w, "| %s\t", col); err != nil { + return err + } + } + if _, err := fmt.Fprintln(w, "|"); err != nil { + return err + } + + // Print separator + for _, col := range header { + if _, err := fmt.Fprintf(w, "| "); err != nil { + return err + } + for range col { + if _, err := fmt.Fprintf(w, "-"); err != nil { + return err + } + } + if _, err := fmt.Fprintf(w, "\t"); err != nil { + return err + } + } + if _, err := fmt.Fprintln(w, "|"); err != nil { + return err + } + + // Print rows -- `consumeRows` will call this function once for each row. + if err := consumeRows(func(row ...string) error { + for _, col := range row { + if _, err := fmt.Fprintf(w, "| %s\t", col); err != nil { + return err + } + } + if _, err := fmt.Fprintln(w, "|"); err != nil { + return err + } + return nil + }); err != nil { + return err + } + + // Flush the buffer and print the table + if err := w.Flush(); err != nil { + return err + } + + return nil +} + func logMessage(logger *modules.Logger, msg, hostname string, peer types.Peer) { remoteHostname, _, err := net.SplitHostPort(peer.GetServiceURL()) if err != nil { diff --git a/runtime/configs/proto/p2p_config.proto b/runtime/configs/proto/p2p_config.proto index c331176fa..1e01d36fb 100644 --- a/runtime/configs/proto/p2p_config.proto +++ b/runtime/configs/proto/p2p_config.proto @@ -14,4 +14,5 @@ message P2PConfig { uint64 max_nonces = 5; // used to limit the number of nonces that can be stored before a FIFO mechanism is used to remove the oldest nonces and make space for the new ones bool is_client_only = 6; // TECHDEBT(bryanchriswhite,olshansky): Re-evaluate if this is still needed string bootstrap_nodes_csv = 7; // string in the format "http://somenode:50832,http://someothernode:50832". Refer to `p2p/module_test.go` for additional details. + bool enable_peer_discovery_debug_rpc = 8; // enables a debug endpoint for various operations related to p2p peer discovery } diff --git a/shared/messaging/proto/debug_message.proto b/shared/messaging/proto/debug_message.proto index 7ce079afa..eebaaa11a 100644 --- a/shared/messaging/proto/debug_message.proto +++ b/shared/messaging/proto/debug_message.proto @@ -7,35 +7,34 @@ import "google/protobuf/any.proto"; option go_package = "github.com/pokt-network/pocket/shared/messaging"; enum DebugMessageAction { - DEBUG_ACTION_UNKNOWN = 0; + DEBUG_ACTION_UNKNOWN = 0; - DEBUG_CONSENSUS_RESET_TO_GENESIS = 1; - DEBUG_CONSENSUS_PRINT_NODE_STATE = 2; - DEBUG_CONSENSUS_TRIGGER_NEXT_VIEW = 3; - DEBUG_CONSENSUS_TOGGLE_PACE_MAKER_MODE = 4; // toggle between manual and automatic - - // TODO: Replace `DEBUG_` with `DEBUG_PERSISTENCE_` below for clarity - DEBUG_CONSENSUS_SEND_METADATA_REQ = 5; - DEBUG_CONSENSUS_SEND_BLOCK_REQ = 6; + DEBUG_CONSENSUS_RESET_TO_GENESIS = 1; + DEBUG_CONSENSUS_PRINT_NODE_STATE = 2; + DEBUG_CONSENSUS_TRIGGER_NEXT_VIEW = 3; + DEBUG_CONSENSUS_TOGGLE_PACE_MAKER_MODE = 4; // toggle between manual and automatic - DEBUG_SHOW_LATEST_BLOCK_IN_STORE = 7; + DEBUG_CONSENSUS_SEND_METADATA_REQ = 5; + DEBUG_CONSENSUS_SEND_BLOCK_REQ = 6; - DEBUG_PERSISTENCE_CLEAR_STATE = 8; - DEBUG_PERSISTENCE_RESET_TO_GENESIS = 9; + DEBUG_SHOW_LATEST_BLOCK_IN_STORE = 7; // TODO: Replace `DEBUG_` with `DEBUG_PERSISTENCE_` + DEBUG_PERSISTENCE_CLEAR_STATE = 8; + DEBUG_PERSISTENCE_RESET_TO_GENESIS = 9; + + DEBUG_P2P_PRINT_PEER_LIST = 10; } message DebugMessage { - DebugMessageAction action = 1; - DebugMessageRoutingType type = 2; - google.protobuf.Any message = 3; + DebugMessageAction action = 1; + DebugMessageRoutingType type = 2; + google.protobuf.Any message = 3; } // NB: See https://en.wikipedia.org/wiki/Routing for more info on routing and delivery schemes. enum DebugMessageRoutingType { - DEBUG_MESSAGE_TYPE_UNKNOWN = 0; - - DEBUG_MESSAGE_TYPE_ANYCAST = 1; - DEBUG_MESSAGE_TYPE_MULTICAST = 2; - DEBUG_MESSAGE_TYPE_BROADCAST = 3; - DEBUG_MESSAGE_TYPE_UNICAST = 4; -} \ No newline at end of file + DEBUG_MESSAGE_TYPE_UNKNOWN = 0; + DEBUG_MESSAGE_TYPE_ANYCAST = 1; + DEBUG_MESSAGE_TYPE_MULTICAST = 2; + DEBUG_MESSAGE_TYPE_BROADCAST = 3; + DEBUG_MESSAGE_TYPE_UNICAST = 4; +} diff --git a/shared/node.go b/shared/node.go index f1e842382..df08f06f3 100644 --- a/shared/node.go +++ b/shared/node.go @@ -205,6 +205,7 @@ func (node *Node) handleDebugMessage(message *messaging.PocketEnvelope) error { return err } switch debugMessage.Action { + // Consensus Debug case messaging.DebugMessageAction_DEBUG_CONSENSUS_RESET_TO_GENESIS, messaging.DebugMessageAction_DEBUG_CONSENSUS_PRINT_NODE_STATE, messaging.DebugMessageAction_DEBUG_CONSENSUS_TRIGGER_NEXT_VIEW, @@ -212,6 +213,9 @@ func (node *Node) handleDebugMessage(message *messaging.PocketEnvelope) error { messaging.DebugMessageAction_DEBUG_CONSENSUS_SEND_BLOCK_REQ, messaging.DebugMessageAction_DEBUG_CONSENSUS_SEND_METADATA_REQ: return node.GetBus().GetConsensusModule().HandleDebugMessage(debugMessage) + // P2P Debug + case messaging.DebugMessageAction_DEBUG_P2P_PRINT_PEER_LIST: + return node.GetBus().GetP2PModule().HandleEvent(message.Content) // Persistence Debug case messaging.DebugMessageAction_DEBUG_SHOW_LATEST_BLOCK_IN_STORE: return node.GetBus().GetPersistenceModule().HandleDebugMessage(debugMessage)