cmd/devp2p: add eth protocol test suite (#21598)
This change adds a test framework for the "eth" protocol and some basic tests. The tests can be run using the './devp2p rlpx eth-test' command.
This commit is contained in:
@ -19,9 +19,11 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/ethtest"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/internal/utesting"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/p2p/rlpx"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
@ -34,38 +36,42 @@ var (
|
||||
Usage: "RLPx Commands",
|
||||
Subcommands: []cli.Command{
|
||||
rlpxPingCommand,
|
||||
rlpxEthTestCommand,
|
||||
},
|
||||
}
|
||||
rlpxPingCommand = cli.Command{
|
||||
Name: "ping",
|
||||
Usage: "Perform a RLPx handshake",
|
||||
ArgsUsage: "<node>",
|
||||
Action: rlpxPing,
|
||||
Name: "ping",
|
||||
Usage: "ping <node>",
|
||||
Action: rlpxPing,
|
||||
}
|
||||
rlpxEthTestCommand = cli.Command{
|
||||
Name: "eth-test",
|
||||
Usage: "Runs tests against a node",
|
||||
ArgsUsage: "<node> <path_to_chain.rlp_file>",
|
||||
Action: rlpxEthTest,
|
||||
Flags: []cli.Flag{testPatternFlag},
|
||||
}
|
||||
)
|
||||
|
||||
func rlpxPing(ctx *cli.Context) error {
|
||||
n := getNodeArg(ctx)
|
||||
|
||||
fd, err := net.Dial("tcp", fmt.Sprintf("%v:%d", n.IP(), n.TCP()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conn := rlpx.NewConn(fd, n.Pubkey())
|
||||
|
||||
ourKey, _ := crypto.GenerateKey()
|
||||
_, err = conn.Handshake(ourKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
code, data, _, err := conn.Read()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch code {
|
||||
case 0:
|
||||
var h devp2pHandshake
|
||||
var h ethtest.Hello
|
||||
if err := rlp.DecodeBytes(data, &h); err != nil {
|
||||
return fmt.Errorf("invalid handshake: %v", err)
|
||||
}
|
||||
@ -82,13 +88,22 @@ func rlpxPing(ctx *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// devp2pHandshake is the RLP structure of the devp2p protocol handshake.
|
||||
type devp2pHandshake struct {
|
||||
Version uint64
|
||||
Name string
|
||||
Caps []p2p.Cap
|
||||
ListenPort uint64
|
||||
ID hexutil.Bytes // secp256k1 public key
|
||||
// Ignore additional fields (for forward compatibility).
|
||||
Rest []rlp.RawValue `rlp:"tail"`
|
||||
func rlpxEthTest(ctx *cli.Context) error {
|
||||
if ctx.NArg() < 3 {
|
||||
exit("missing path to chain.rlp as command-line argument")
|
||||
}
|
||||
|
||||
suite := ethtest.NewSuite(getNodeArg(ctx), ctx.Args()[1], ctx.Args()[2])
|
||||
|
||||
// Filter and run test cases.
|
||||
tests := suite.AllTests()
|
||||
if ctx.IsSet(testPatternFlag.Name) {
|
||||
tests = utesting.MatchTests(tests, ctx.String(testPatternFlag.Name))
|
||||
}
|
||||
results := utesting.RunTests(tests, os.Stdout)
|
||||
if fails := utesting.CountFailures(results); fails > 0 {
|
||||
return fmt.Errorf("%v of %v tests passed.", len(tests)-fails, len(tests))
|
||||
}
|
||||
fmt.Printf("all tests passed\n")
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user