-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[P2P] [Tooling] Peer discovery peer connections
subcommand
#801
base: feat/peer-discovery-list
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,80 @@ | ||||||||||||||
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/p2p/debug" | ||||||||||||||
"github.com/pokt-network/pocket/shared/messaging" | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
var ( | ||||||||||||||
connectionsCmd = &cobra.Command{ | ||||||||||||||
Use: "connections", | ||||||||||||||
Short: "Print open peer connections", | ||||||||||||||
Comment on lines
+16
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
RunE: connectionsRunE, | ||||||||||||||
} | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
func init() { | ||||||||||||||
PeerCmd.AddCommand(connectionsCmd) | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
func connectionsRunE(cmd *cobra.Command, _ []string) error { | ||||||||||||||
var routerType debug.RouterType | ||||||||||||||
|
||||||||||||||
bus, err := helpers.GetBusFromCmd(cmd) | ||||||||||||||
if err != nil { | ||||||||||||||
return err | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
switch { | ||||||||||||||
case stakedFlag: | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OPTIONAL: The way I would've done this is by having a smaller private helper function like below that returns the router typ: func foo() routerType {
switch
case stakedFlag && !unstakedFlag && !allFlag {
return debug.StakeRouterType
}
case unstakedFlag && !stakedFlag && !allFlag {
return debug.UnstakedRouterType
}
case stakedFlag || unstakedFlag {
return ErrRouterType
}
// even if `allFlag` is false, we still want to print all connections
default:
return debug.AllRouterTypes
}
} Wdyt? |
||||||||||||||
if unstakedFlag || allFlag { | ||||||||||||||
return ErrRouterType | ||||||||||||||
} | ||||||||||||||
routerType = debug.StakedRouterType | ||||||||||||||
case unstakedFlag: | ||||||||||||||
if stakedFlag || allFlag { | ||||||||||||||
return ErrRouterType | ||||||||||||||
} | ||||||||||||||
routerType = debug.UnstakedRouterType | ||||||||||||||
// even if `allFlag` is false, we still want to print all connections | ||||||||||||||
default: | ||||||||||||||
if stakedFlag || unstakedFlag { | ||||||||||||||
return ErrRouterType | ||||||||||||||
} | ||||||||||||||
routerType = debug.AllRouterTypes | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
debugMsg := &messaging.DebugMessage{ | ||||||||||||||
Action: messaging.DebugMessageAction_DEBUG_P2P_PEER_CONNECTIONS, | ||||||||||||||
Type: messaging.DebugMessageRoutingType_DEBUG_MESSAGE_TYPE_BROADCAST, | ||||||||||||||
Message: &anypb.Any{ | ||||||||||||||
Value: []byte(routerType), | ||||||||||||||
}, | ||||||||||||||
} | ||||||||||||||
debugMsgAny, err := anypb.New(debugMsg) | ||||||||||||||
if err != nil { | ||||||||||||||
return fmt.Errorf("creating anypb from debug message: %w", err) | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
if localFlag { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So if this is false we don't print anything? I don't fully understand its use. Is it like a "verbose" flag? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This |
||||||||||||||
if err := debug.PrintPeerConnections(bus, routerType); err != nil { | ||||||||||||||
return fmt.Errorf("printing peer list: %w", err) | ||||||||||||||
} | ||||||||||||||
return nil | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
// TECHDEBT(#810, #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 | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So why don't we do this? |
||||||||||||||
// instance could persist between commands. Other interactive CLI commands which | ||||||||||||||
// rely on unstaked actor router broadcast are working as expected. | ||||||||||||||
|
||||||||||||||
// TECHDEBT(#810, #811): use broadcast instead to reach all peers. | ||||||||||||||
return sendToStakedPeers(cmd, debugMsgAny) | ||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -100,6 +100,7 @@ config: | |
use_rain_tree: true | ||
is_empty_connection_type: false | ||
private_key: "" # @ignored This value is needed but ignored - use privateKeySecretKeyRef instead | ||
# TODO: I think this has been renamed to `max_nonces` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
max_mempool_count: 100000 | ||
enable_peer_discovery_debug_rpc: false | ||
telemetry: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,8 @@ import ( | |
|
||
func (m *p2pModule) handleDebugMessage(msg *messaging.DebugMessage) error { | ||
switch msg.Action { | ||
case messaging.DebugMessageAction_DEBUG_P2P_PEER_LIST: | ||
case messaging.DebugMessageAction_DEBUG_P2P_PEER_LIST, | ||
messaging.DebugMessageAction_DEBUG_P2P_PEER_CONNECTIONS: | ||
if !m.cfg.EnablePeerDiscoveryDebugRpc { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like we can skip the first switch statement and just return (with a debug log or error) if |
||
return typesP2P.ErrPeerDiscoveryDebugRPCDisabled | ||
} | ||
|
@@ -23,6 +24,9 @@ func (m *p2pModule) handleDebugMessage(msg *messaging.DebugMessage) error { | |
case messaging.DebugMessageAction_DEBUG_P2P_PEER_LIST: | ||
routerType := debug.RouterType(msg.Message.Value) | ||
return debug.PrintPeerList(m.GetBus(), routerType) | ||
case messaging.DebugMessageAction_DEBUG_P2P_PEER_CONNECTIONS: | ||
routerType := debug.RouterType(msg.Message.Value) | ||
return debug.PrintPeerConnections(m.GetBus(), routerType) | ||
default: | ||
return fmt.Errorf("unsupported P2P debug message action: %s", msg.Action) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
package debug | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we add a debug build tag? |
||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"strconv" | ||
|
||
libp2pNetwork "github.com/libp2p/go-libp2p/core/network" | ||
libp2pPeer "github.com/libp2p/go-libp2p/core/peer" | ||
|
||
"github.com/pokt-network/pocket/p2p/providers/peerstore_provider" | ||
typesP2P "github.com/pokt-network/pocket/p2p/types" | ||
"github.com/pokt-network/pocket/p2p/utils" | ||
"github.com/pokt-network/pocket/shared/modules" | ||
) | ||
|
||
var printConnectionsHeader = []string{"Peer ID", "Multiaddr", "Opened", "Direction", "NumStreams"} | ||
|
||
func PrintPeerConnections(bus modules.Bus, routerType RouterType) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please add godoco comments for functions exposed outside of this pacakge |
||
var ( | ||
connections []libp2pNetwork.Conn | ||
routerPlurality = "" | ||
) | ||
|
||
if routerType == AllRouterTypes { | ||
routerPlurality = "s" | ||
} | ||
|
||
connections, err := getFilteredConnections(bus, routerType) | ||
if err != nil { | ||
return fmt.Errorf("getting connecions: %w", err) | ||
} | ||
|
||
if err := LogSelfAddress(bus); err != nil { | ||
return fmt.Errorf("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.) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To rephrase, it doesn't seem like writing to stdout with anything other than tabwriter produces any output in the logs. |
||
if _, err := fmt.Fprintf( | ||
os.Stdout, | ||
"%s router peerstore%s:\n", | ||
routerType, | ||
routerPlurality, | ||
); err != nil { | ||
return fmt.Errorf("printing to stdout: %w", err) | ||
} | ||
|
||
if err := PrintConnectionsTable(connections); err != nil { | ||
return fmt.Errorf("printing peer list: %w", err) | ||
} | ||
return nil | ||
} | ||
|
||
func PrintConnectionsTable(conns []libp2pNetwork.Conn) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does |
||
return utils.PrintTable(printConnectionsHeader, peerConnsRowConsumerFactory(conns)) | ||
} | ||
|
||
func getFilteredConnections( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you comment what filter does? For example: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Returns only connections with identities matching those found in the given router type. |
||
bus modules.Bus, | ||
routerType RouterType, | ||
) ([]libp2pNetwork.Conn, error) { | ||
var ( | ||
pstore typesP2P.Peerstore | ||
idsToInclude map[libp2pPeer.ID]struct{} | ||
p2pModule = bus.GetP2PModule() | ||
connections = p2pModule.GetConnections() | ||
) | ||
|
||
// TECHDEBT(#810, #811): use `bus.GetPeerstoreProvider()` after peerstore provider | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 810 is resolved . Ditto elsewhere |
||
// is retrievable as a proper submodule. | ||
pstoreProviderModule, err := bus.GetModulesRegistry(). | ||
GetModule(peerstore_provider.PeerstoreProviderSubmoduleName) | ||
if err != nil { | ||
return nil, fmt.Errorf("getting peerstore provider: %w", err) | ||
} | ||
pstoreProvider, ok := pstoreProviderModule.(peerstore_provider.PeerstoreProvider) | ||
if !ok { | ||
return nil, fmt.Errorf("unknown peerstore provider type: %T", pstoreProviderModule) | ||
} | ||
//-- | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rm? |
||
|
||
switch routerType { | ||
case AllRouterTypes: | ||
// return early; no need to filter | ||
return connections, nil | ||
case StakedRouterType: | ||
pstore, err = pstoreProvider.GetStakedPeerstoreAtCurrentHeight() | ||
if err != nil { | ||
return nil, fmt.Errorf("getting staked peerstore: %w", err) | ||
} | ||
case UnstakedRouterType: | ||
pstore, err = pstoreProvider.GetUnstakedPeerstore() | ||
if err != nil { | ||
return nil, fmt.Errorf("getting unstaked peerstore: %w", err) | ||
} | ||
} | ||
|
||
idsToInclude, err = getPeerIDs(pstore.GetPeerList()) | ||
if err != nil { | ||
return nil, fmt.Errorf("getting peer IDs: %w", err) | ||
} | ||
|
||
var filteredConnections []libp2pNetwork.Conn | ||
for _, conn := range connections { | ||
if _, ok := idsToInclude[conn.RemotePeer()]; ok { | ||
filteredConnections = append(filteredConnections, conn) | ||
} | ||
} | ||
return filteredConnections, nil | ||
} | ||
|
||
func peerConnsRowConsumerFactory(conns []libp2pNetwork.Conn) utils.RowConsumer { | ||
return func(provideRow utils.RowProvider) error { | ||
for _, conn := range conns { | ||
if err := provideRow( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what happens if we don't return an error when |
||
conn.RemotePeer().String(), | ||
conn.RemoteMultiaddr().String(), | ||
conn.Stat().Opened.String(), | ||
conn.Stat().Direction.String(), | ||
strconv.Itoa(conn.Stat().NumStreams), | ||
); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
} | ||
|
||
func getPeerIDs(peers []typesP2P.Peer) (map[libp2pPeer.ID]struct{}, error) { | ||
ids := make(map[libp2pPeer.ID]struct{}) | ||
for _, peer := range peers { | ||
addrInfo, err := utils.Libp2pAddrInfoFromPeer(peer) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// ID already in set; continue | ||
if _, ok := ids[addrInfo.ID]; ok { | ||
continue | ||
} | ||
|
||
// add ID to set | ||
ids[addrInfo.ID] = struct{}{} | ||
} | ||
return ids, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everywhere else we have a function that returns a new instance of
cobra.Command
.I think we should either: