rlpxcmd.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright 2020 The go-ethereum Authors
  2. // This file is part of go-ethereum.
  3. //
  4. // go-ethereum is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // go-ethereum is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  16. package main
  17. import (
  18. "fmt"
  19. "net"
  20. "github.com/ethereum/go-ethereum/common/hexutil"
  21. "github.com/ethereum/go-ethereum/crypto"
  22. "github.com/ethereum/go-ethereum/p2p"
  23. "github.com/ethereum/go-ethereum/p2p/rlpx"
  24. "github.com/ethereum/go-ethereum/rlp"
  25. "gopkg.in/urfave/cli.v1"
  26. )
  27. var (
  28. rlpxCommand = cli.Command{
  29. Name: "rlpx",
  30. Usage: "RLPx Commands",
  31. Subcommands: []cli.Command{
  32. rlpxPingCommand,
  33. },
  34. }
  35. rlpxPingCommand = cli.Command{
  36. Name: "ping",
  37. Usage: "Perform a RLPx handshake",
  38. ArgsUsage: "<node>",
  39. Action: rlpxPing,
  40. }
  41. )
  42. func rlpxPing(ctx *cli.Context) error {
  43. n := getNodeArg(ctx)
  44. fd, err := net.Dial("tcp", fmt.Sprintf("%v:%d", n.IP(), n.TCP()))
  45. if err != nil {
  46. return err
  47. }
  48. conn := rlpx.NewConn(fd, n.Pubkey())
  49. ourKey, _ := crypto.GenerateKey()
  50. _, err = conn.Handshake(ourKey)
  51. if err != nil {
  52. return err
  53. }
  54. code, data, _, err := conn.Read()
  55. if err != nil {
  56. return err
  57. }
  58. switch code {
  59. case 0:
  60. var h devp2pHandshake
  61. if err := rlp.DecodeBytes(data, &h); err != nil {
  62. return fmt.Errorf("invalid handshake: %v", err)
  63. }
  64. fmt.Printf("%+v\n", h)
  65. case 1:
  66. var msg []p2p.DiscReason
  67. if rlp.DecodeBytes(data, &msg); len(msg) == 0 {
  68. return fmt.Errorf("invalid disconnect message")
  69. }
  70. return fmt.Errorf("received disconnect message: %v", msg[0])
  71. default:
  72. return fmt.Errorf("invalid message code %d, expected handshake (code zero)", code)
  73. }
  74. return nil
  75. }
  76. // devp2pHandshake is the RLP structure of the devp2p protocol handshake.
  77. type devp2pHandshake struct {
  78. Version uint64
  79. Name string
  80. Caps []p2p.Cap
  81. ListenPort uint64
  82. ID hexutil.Bytes // secp256k1 public key
  83. // Ignore additional fields (for forward compatibility).
  84. Rest []rlp.RawValue `rlp:"tail"`
  85. }