github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/cmd/devp2p/rlpxcmd.go (about) 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 17 package main 18 19 import ( 20 "errors" 21 "fmt" 22 "net" 23 24 "github.com/ethereum/go-ethereum/cmd/devp2p/internal/ethtest" 25 "github.com/ethereum/go-ethereum/crypto" 26 "github.com/ethereum/go-ethereum/p2p" 27 "github.com/ethereum/go-ethereum/p2p/enode" 28 "github.com/ethereum/go-ethereum/p2p/rlpx" 29 "github.com/ethereum/go-ethereum/rlp" 30 "github.com/urfave/cli/v2" 31 ) 32 33 var ( 34 rlpxCommand = &cli.Command{ 35 Name: "rlpx", 36 Usage: "RLPx Commands", 37 Subcommands: []*cli.Command{ 38 rlpxPingCommand, 39 rlpxEthTestCommand, 40 rlpxSnapTestCommand, 41 }, 42 } 43 rlpxPingCommand = &cli.Command{ 44 Name: "ping", 45 Usage: "ping <node>", 46 Action: rlpxPing, 47 } 48 rlpxEthTestCommand = &cli.Command{ 49 Name: "eth-test", 50 Usage: "Runs eth protocol tests against a node", 51 ArgsUsage: "<node>", 52 Action: rlpxEthTest, 53 Flags: []cli.Flag{ 54 testPatternFlag, 55 testTAPFlag, 56 testChainDirFlag, 57 testNodeFlag, 58 testNodeJWTFlag, 59 testNodeEngineFlag, 60 }, 61 } 62 rlpxSnapTestCommand = &cli.Command{ 63 Name: "snap-test", 64 Usage: "Runs snap protocol tests against a node", 65 ArgsUsage: "", 66 Action: rlpxSnapTest, 67 Flags: []cli.Flag{ 68 testPatternFlag, 69 testTAPFlag, 70 testChainDirFlag, 71 testNodeFlag, 72 testNodeJWTFlag, 73 testNodeEngineFlag, 74 }, 75 } 76 ) 77 78 func rlpxPing(ctx *cli.Context) error { 79 n := getNodeArg(ctx) 80 fd, err := net.Dial("tcp", fmt.Sprintf("%v:%d", n.IP(), n.TCP())) 81 if err != nil { 82 return err 83 } 84 conn := rlpx.NewConn(fd, n.Pubkey()) 85 ourKey, _ := crypto.GenerateKey() 86 _, err = conn.Handshake(ourKey) 87 if err != nil { 88 return err 89 } 90 code, data, _, err := conn.Read() 91 if err != nil { 92 return err 93 } 94 switch code { 95 case 0: 96 var h ethtest.Hello 97 if err := rlp.DecodeBytes(data, &h); err != nil { 98 return fmt.Errorf("invalid handshake: %v", err) 99 } 100 fmt.Printf("%+v\n", h) 101 case 1: 102 var msg []p2p.DiscReason 103 if rlp.DecodeBytes(data, &msg); len(msg) == 0 { 104 return errors.New("invalid disconnect message") 105 } 106 return fmt.Errorf("received disconnect message: %v", msg[0]) 107 default: 108 return fmt.Errorf("invalid message code %d, expected handshake (code zero)", code) 109 } 110 return nil 111 } 112 113 // rlpxEthTest runs the eth protocol test suite. 114 func rlpxEthTest(ctx *cli.Context) error { 115 p := cliTestParams(ctx) 116 suite, err := ethtest.NewSuite(p.node, p.chainDir, p.engineAPI, p.jwt) 117 if err != nil { 118 exit(err) 119 } 120 return runTests(ctx, suite.EthTests()) 121 } 122 123 // rlpxSnapTest runs the snap protocol test suite. 124 func rlpxSnapTest(ctx *cli.Context) error { 125 p := cliTestParams(ctx) 126 suite, err := ethtest.NewSuite(p.node, p.chainDir, p.engineAPI, p.jwt) 127 if err != nil { 128 exit(err) 129 } 130 return runTests(ctx, suite.SnapTests()) 131 } 132 133 type testParams struct { 134 node *enode.Node 135 engineAPI string 136 jwt string 137 chainDir string 138 } 139 140 func cliTestParams(ctx *cli.Context) *testParams { 141 nodeStr := ctx.String(testNodeFlag.Name) 142 if nodeStr == "" { 143 exit(fmt.Errorf("missing -%s", testNodeFlag.Name)) 144 } 145 node, err := parseNode(nodeStr) 146 if err != nil { 147 exit(err) 148 } 149 p := testParams{ 150 node: node, 151 engineAPI: ctx.String(testNodeEngineFlag.Name), 152 jwt: ctx.String(testNodeJWTFlag.Name), 153 chainDir: ctx.String(testChainDirFlag.Name), 154 } 155 if p.engineAPI == "" { 156 exit(fmt.Errorf("missing -%s", testNodeEngineFlag.Name)) 157 } 158 if p.jwt == "" { 159 exit(fmt.Errorf("missing -%s", testNodeJWTFlag.Name)) 160 } 161 if p.chainDir == "" { 162 exit(fmt.Errorf("missing -%s", testChainDirFlag.Name)) 163 } 164 return &p 165 }