Unverified Commit d804a59e authored by Felix Lange's avatar Felix Lange Committed by GitHub

cmd/devp2p/internal/ethtest: update tests for eth/67 (#25306)

parent 6fdc6194
......@@ -96,12 +96,12 @@ func (c *Chain) Head() *types.Block {
return c.blocks[c.Len()-1]
}
func (c *Chain) GetHeaders(req GetBlockHeaders) (BlockHeaders, error) {
func (c *Chain) GetHeaders(req *GetBlockHeaders) ([]*types.Header, error) {
if req.Amount < 1 {
return nil, fmt.Errorf("no block headers requested")
}
headers := make(BlockHeaders, req.Amount)
headers := make([]*types.Header, req.Amount)
var blockNumber uint64
// range over blocks to check if our chain has the requested header
......
......@@ -21,6 +21,7 @@ import (
"strconv"
"testing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/p2p"
"github.com/stretchr/testify/assert"
......@@ -140,18 +141,18 @@ func TestChain_GetHeaders(t *testing.T) {
var tests = []struct {
req GetBlockHeaders
expected BlockHeaders
expected []*types.Header
}{
{
req: GetBlockHeaders{
Origin: eth.HashOrNumber{
Number: uint64(2),
GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Origin: eth.HashOrNumber{Number: uint64(2)},
Amount: uint64(5),
Skip: 1,
Reverse: false,
},
Amount: uint64(5),
Skip: 1,
Reverse: false,
},
expected: BlockHeaders{
expected: []*types.Header{
chain.blocks[2].Header(),
chain.blocks[4].Header(),
chain.blocks[6].Header(),
......@@ -161,14 +162,14 @@ func TestChain_GetHeaders(t *testing.T) {
},
{
req: GetBlockHeaders{
Origin: eth.HashOrNumber{
Number: uint64(chain.Len() - 1),
GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Origin: eth.HashOrNumber{Number: uint64(chain.Len() - 1)},
Amount: uint64(3),
Skip: 0,
Reverse: true,
},
Amount: uint64(3),
Skip: 0,
Reverse: true,
},
expected: BlockHeaders{
expected: []*types.Header{
chain.blocks[chain.Len()-1].Header(),
chain.blocks[chain.Len()-2].Header(),
chain.blocks[chain.Len()-3].Header(),
......@@ -176,14 +177,14 @@ func TestChain_GetHeaders(t *testing.T) {
},
{
req: GetBlockHeaders{
Origin: eth.HashOrNumber{
Hash: chain.Head().Hash(),
GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Origin: eth.HashOrNumber{Hash: chain.Head().Hash()},
Amount: uint64(1),
Skip: 0,
Reverse: false,
},
Amount: uint64(1),
Skip: 0,
Reverse: false,
},
expected: BlockHeaders{
expected: []*types.Header{
chain.Head().Header(),
},
},
......@@ -191,7 +192,7 @@ func TestChain_GetHeaders(t *testing.T) {
for i, tt := range tests {
t.Run(strconv.Itoa(i), func(t *testing.T) {
headers, err := chain.GetHeaders(tt.req)
headers, err := chain.GetHeaders(&tt.req)
if err != nil {
t.Fatal(err)
}
......
This diff is collapsed.
......@@ -21,32 +21,40 @@ import "github.com/ethereum/go-ethereum/eth/protocols/snap"
// GetAccountRange represents an account range query.
type GetAccountRange snap.GetAccountRangePacket
func (g GetAccountRange) Code() int { return 33 }
func (msg GetAccountRange) Code() int { return 33 }
func (msg GetAccountRange) ReqID() uint64 { return msg.ID }
type AccountRange snap.AccountRangePacket
func (g AccountRange) Code() int { return 34 }
func (msg AccountRange) Code() int { return 34 }
func (msg AccountRange) ReqID() uint64 { return msg.ID }
type GetStorageRanges snap.GetStorageRangesPacket
func (g GetStorageRanges) Code() int { return 35 }
func (msg GetStorageRanges) Code() int { return 35 }
func (msg GetStorageRanges) ReqID() uint64 { return msg.ID }
type StorageRanges snap.StorageRangesPacket
func (g StorageRanges) Code() int { return 36 }
func (msg StorageRanges) Code() int { return 36 }
func (msg StorageRanges) ReqID() uint64 { return msg.ID }
type GetByteCodes snap.GetByteCodesPacket
func (g GetByteCodes) Code() int { return 37 }
func (msg GetByteCodes) Code() int { return 37 }
func (msg GetByteCodes) ReqID() uint64 { return msg.ID }
type ByteCodes snap.ByteCodesPacket
func (g ByteCodes) Code() int { return 38 }
func (msg ByteCodes) Code() int { return 38 }
func (msg ByteCodes) ReqID() uint64 { return msg.ID }
type GetTrieNodes snap.GetTrieNodesPacket
func (g GetTrieNodes) Code() int { return 39 }
func (msg GetTrieNodes) Code() int { return 39 }
func (msg GetTrieNodes) ReqID() uint64 { return msg.ID }
type TrieNodes snap.TrieNodesPacket
func (g TrieNodes) Code() int { return 40 }
func (msg TrieNodes) Code() int { return 40 }
func (msg TrieNodes) ReqID() uint64 { return msg.ID }
This diff is collapsed.
......@@ -45,7 +45,7 @@ func TestEthSuite(t *testing.T) {
if err != nil {
t.Fatalf("could not create new test suite: %v", err)
}
for _, test := range suite.Eth66Tests() {
for _, test := range suite.EthTests() {
t.Run(test.Name, func(t *testing.T) {
result := utesting.RunTAP([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout)
if result[0].Failed {
......
......@@ -32,7 +32,7 @@ import (
//var faucetAddr = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
var faucetKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
func (s *Suite) sendSuccessfulTxs(t *utesting.T, isEth66 bool) error {
func (s *Suite) sendSuccessfulTxs(t *utesting.T) error {
tests := []*types.Transaction{
getNextTxFromChain(s),
unknownTx(s),
......@@ -48,15 +48,15 @@ func (s *Suite) sendSuccessfulTxs(t *utesting.T, isEth66 bool) error {
prevTx = tests[i-1]
}
// write tx to connection
if err := sendSuccessfulTx(s, tx, prevTx, isEth66); err != nil {
if err := sendSuccessfulTx(s, tx, prevTx); err != nil {
return fmt.Errorf("send successful tx test failed: %v", err)
}
}
return nil
}
func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction, isEth66 bool) error {
sendConn, recvConn, err := s.createSendAndRecvConns(isEth66)
func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction) error {
sendConn, recvConn, err := s.createSendAndRecvConns()
if err != nil {
return err
}
......@@ -73,8 +73,10 @@ func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction
if err = recvConn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err)
}
// update last nonce seen
nonce = tx.Nonce()
// Wait for the transaction announcement
for {
switch msg := recvConn.readAndServe(s.chain, timeout).(type) {
......@@ -114,7 +116,7 @@ func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction
}
}
func (s *Suite) sendMaliciousTxs(t *utesting.T, isEth66 bool) error {
func (s *Suite) sendMaliciousTxs(t *utesting.T) error {
badTxs := []*types.Transaction{
getOldTxFromChain(s),
invalidNonceTx(s),
......@@ -122,16 +124,9 @@ func (s *Suite) sendMaliciousTxs(t *utesting.T, isEth66 bool) error {
hugeGasPrice(s),
hugeData(s),
}
// setup receiving connection before sending malicious txs
var (
recvConn *Conn
err error
)
if isEth66 {
recvConn, err = s.dial66()
} else {
recvConn, err = s.dial()
}
recvConn, err := s.dial()
if err != nil {
return fmt.Errorf("dial failed: %v", err)
}
......@@ -139,9 +134,10 @@ func (s *Suite) sendMaliciousTxs(t *utesting.T, isEth66 bool) error {
if err = recvConn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err)
}
for i, tx := range badTxs {
t.Logf("Testing malicious tx propagation: %v\n", i)
if err = sendMaliciousTx(s, tx, isEth66); err != nil {
if err = sendMaliciousTx(s, tx); err != nil {
return fmt.Errorf("malicious tx test failed:\ntx: %v\nerror: %v", tx, err)
}
}
......@@ -149,17 +145,8 @@ func (s *Suite) sendMaliciousTxs(t *utesting.T, isEth66 bool) error {
return checkMaliciousTxPropagation(s, badTxs, recvConn)
}
func sendMaliciousTx(s *Suite, tx *types.Transaction, isEth66 bool) error {
// setup connection
var (
conn *Conn
err error
)
if isEth66 {
conn, err = s.dial66()
} else {
conn, err = s.dial()
}
func sendMaliciousTx(s *Suite, tx *types.Transaction) error {
conn, err := s.dial()
if err != nil {
return fmt.Errorf("dial failed: %v", err)
}
......@@ -167,6 +154,7 @@ func sendMaliciousTx(s *Suite, tx *types.Transaction, isEth66 bool) error {
if err = conn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err)
}
// write malicious tx
if err = conn.Write(&Transactions{tx}); err != nil {
return fmt.Errorf("failed to write to connection: %v", err)
......@@ -182,7 +170,7 @@ func sendMultipleSuccessfulTxs(t *utesting.T, s *Suite, txs []*types.Transaction
txMsg := Transactions(txs)
t.Logf("sending %d txs\n", len(txs))
sendConn, recvConn, err := s.createSendAndRecvConns(true)
sendConn, recvConn, err := s.createSendAndRecvConns()
if err != nil {
return err
}
......@@ -194,15 +182,19 @@ func sendMultipleSuccessfulTxs(t *utesting.T, s *Suite, txs []*types.Transaction
if err = recvConn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err)
}
// Send the transactions
if err = sendConn.Write(&txMsg); err != nil {
return fmt.Errorf("failed to write message to connection: %v", err)
}
// update nonce
nonce = txs[len(txs)-1].Nonce()
// Wait for the transaction announcement(s) and make sure all sent txs are being propagated
// Wait for the transaction announcement(s) and make sure all sent txs are being propagated.
// all txs should be announced within 3 announcements.
recvHashes := make([]common.Hash, 0)
// all txs should be announced within 3 announcements
for i := 0; i < 3; i++ {
switch msg := recvConn.readAndServe(s.chain, timeout).(type) {
case *Transactions:
......
......@@ -29,6 +29,7 @@ import (
type Message interface {
Code() int
ReqID() uint64
}
type Error struct {
......@@ -37,9 +38,11 @@ type Error struct {
func (e *Error) Unwrap() error { return e.err }
func (e *Error) Error() string { return e.err.Error() }
func (e *Error) Code() int { return -1 }
func (e *Error) String() string { return e.Error() }
func (e *Error) Code() int { return -1 }
func (e *Error) ReqID() uint64 { return 0 }
func errorf(format string, args ...interface{}) *Error {
return &Error{fmt.Errorf(format, args...)}
}
......@@ -56,73 +59,88 @@ type Hello struct {
Rest []rlp.RawValue `rlp:"tail"`
}
func (h Hello) Code() int { return 0x00 }
func (msg Hello) Code() int { return 0x00 }
func (msg Hello) ReqID() uint64 { return 0 }
// Disconnect is the RLP structure for a disconnect message.
type Disconnect struct {
Reason p2p.DiscReason
}
func (d Disconnect) Code() int { return 0x01 }
func (msg Disconnect) Code() int { return 0x01 }
func (msg Disconnect) ReqID() uint64 { return 0 }
type Ping struct{}
func (p Ping) Code() int { return 0x02 }
func (msg Ping) Code() int { return 0x02 }
func (msg Ping) ReqID() uint64 { return 0 }
type Pong struct{}
func (p Pong) Code() int { return 0x03 }
func (msg Pong) Code() int { return 0x03 }
func (msg Pong) ReqID() uint64 { return 0 }
// Status is the network packet for the status message for eth/64 and later.
type Status eth.StatusPacket
func (s Status) Code() int { return 16 }
func (msg Status) Code() int { return 16 }
func (msg Status) ReqID() uint64 { return 0 }
// NewBlockHashes is the network packet for the block announcements.
type NewBlockHashes eth.NewBlockHashesPacket
func (nbh NewBlockHashes) Code() int { return 17 }
func (msg NewBlockHashes) Code() int { return 17 }
func (msg NewBlockHashes) ReqID() uint64 { return 0 }
type Transactions eth.TransactionsPacket
func (t Transactions) Code() int { return 18 }
func (msg Transactions) Code() int { return 18 }
func (msg Transactions) ReqID() uint64 { return 18 }
// GetBlockHeaders represents a block header query.
type GetBlockHeaders eth.GetBlockHeadersPacket
type GetBlockHeaders eth.GetBlockHeadersPacket66
func (g GetBlockHeaders) Code() int { return 19 }
func (msg GetBlockHeaders) Code() int { return 19 }
func (msg GetBlockHeaders) ReqID() uint64 { return msg.RequestId }
type BlockHeaders eth.BlockHeadersPacket
type BlockHeaders eth.BlockHeadersPacket66
func (bh BlockHeaders) Code() int { return 20 }
func (msg BlockHeaders) Code() int { return 20 }
func (msg BlockHeaders) ReqID() uint64 { return msg.RequestId }
// GetBlockBodies represents a GetBlockBodies request
type GetBlockBodies eth.GetBlockBodiesPacket
type GetBlockBodies eth.GetBlockBodiesPacket66
func (gbb GetBlockBodies) Code() int { return 21 }
func (msg GetBlockBodies) Code() int { return 21 }
func (msg GetBlockBodies) ReqID() uint64 { return msg.RequestId }
// BlockBodies is the network packet for block content distribution.
type BlockBodies eth.BlockBodiesPacket
type BlockBodies eth.BlockBodiesPacket66
func (bb BlockBodies) Code() int { return 22 }
func (msg BlockBodies) Code() int { return 22 }
func (msg BlockBodies) ReqID() uint64 { return msg.RequestId }
// NewBlock is the network packet for the block propagation message.
type NewBlock eth.NewBlockPacket
func (nb NewBlock) Code() int { return 23 }
func (msg NewBlock) Code() int { return 23 }
func (msg NewBlock) ReqID() uint64 { return 0 }
// NewPooledTransactionHashes is the network packet for the tx hash propagation message.
type NewPooledTransactionHashes eth.NewPooledTransactionHashesPacket
func (nb NewPooledTransactionHashes) Code() int { return 24 }
func (msg NewPooledTransactionHashes) Code() int { return 24 }
func (msg NewPooledTransactionHashes) ReqID() uint64 { return 0 }
type GetPooledTransactions eth.GetPooledTransactionsPacket
type GetPooledTransactions eth.GetPooledTransactionsPacket66
func (gpt GetPooledTransactions) Code() int { return 25 }
func (msg GetPooledTransactions) Code() int { return 25 }
func (msg GetPooledTransactions) ReqID() uint64 { return msg.RequestId }
type PooledTransactions eth.PooledTransactionsPacket
type PooledTransactions eth.PooledTransactionsPacket66
func (pt PooledTransactions) Code() int { return 26 }
func (msg PooledTransactions) Code() int { return 26 }
func (msg PooledTransactions) ReqID() uint64 { return msg.RequestId }
// Conn represents an individual connection with a peer
type Conn struct {
......@@ -135,62 +153,13 @@ type Conn struct {
caps []p2p.Cap
}
// Read reads an eth packet from the connection.
// Read reads an eth66 packet from the connection.
func (c *Conn) Read() Message {
code, rawData, _, err := c.Conn.Read()
if err != nil {
return errorf("could not read from connection: %v", err)
}
var msg Message
switch int(code) {
case (Hello{}).Code():
msg = new(Hello)
case (Ping{}).Code():
msg = new(Ping)
case (Pong{}).Code():
msg = new(Pong)
case (Disconnect{}).Code():
msg = new(Disconnect)
case (Status{}).Code():
msg = new(Status)
case (GetBlockHeaders{}).Code():
msg = new(GetBlockHeaders)
case (BlockHeaders{}).Code():
msg = new(BlockHeaders)
case (GetBlockBodies{}).Code():
msg = new(GetBlockBodies)
case (BlockBodies{}).Code():
msg = new(BlockBodies)
case (NewBlock{}).Code():
msg = new(NewBlock)
case (NewBlockHashes{}).Code():
msg = new(NewBlockHashes)
case (Transactions{}).Code():
msg = new(Transactions)
case (NewPooledTransactionHashes{}).Code():
msg = new(NewPooledTransactionHashes)
case (GetPooledTransactions{}.Code()):
msg = new(GetPooledTransactions)
case (PooledTransactions{}.Code()):
msg = new(PooledTransactions)
default:
return errorf("invalid message code: %d", code)
}
// if message is devp2p, decode here
if err := rlp.DecodeBytes(rawData, msg); err != nil {
return errorf("could not rlp decode message: %v", err)
}
return msg
}
// Read66 reads an eth66 packet from the connection.
func (c *Conn) Read66() (uint64, Message) {
code, rawData, _, err := c.Conn.Read()
if err != nil {
return 0, errorf("could not read from connection: %v", err)
}
var msg Message
switch int(code) {
case (Hello{}).Code():
......@@ -206,27 +175,27 @@ func (c *Conn) Read66() (uint64, Message) {
case (GetBlockHeaders{}).Code():
ethMsg := new(eth.GetBlockHeadersPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return 0, errorf("could not rlp decode message: %v", err)
return errorf("could not rlp decode message: %v", err)
}
return ethMsg.RequestId, GetBlockHeaders(*ethMsg.GetBlockHeadersPacket)
return (*GetBlockHeaders)(ethMsg)
case (BlockHeaders{}).Code():
ethMsg := new(eth.BlockHeadersPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return 0, errorf("could not rlp decode message: %v", err)
return errorf("could not rlp decode message: %v", err)
}
return ethMsg.RequestId, BlockHeaders(ethMsg.BlockHeadersPacket)
return (*BlockHeaders)(ethMsg)
case (GetBlockBodies{}).Code():
ethMsg := new(eth.GetBlockBodiesPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return 0, errorf("could not rlp decode message: %v", err)
return errorf("could not rlp decode message: %v", err)
}
return ethMsg.RequestId, GetBlockBodies(ethMsg.GetBlockBodiesPacket)
return (*GetBlockBodies)(ethMsg)
case (BlockBodies{}).Code():
ethMsg := new(eth.BlockBodiesPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return 0, errorf("could not rlp decode message: %v", err)
return errorf("could not rlp decode message: %v", err)
}
return ethMsg.RequestId, BlockBodies(ethMsg.BlockBodiesPacket)
return (*BlockBodies)(ethMsg)
case (NewBlock{}).Code():
msg = new(NewBlock)
case (NewBlockHashes{}).Code():
......@@ -238,26 +207,26 @@ func (c *Conn) Read66() (uint64, Message) {
case (GetPooledTransactions{}.Code()):
ethMsg := new(eth.GetPooledTransactionsPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return 0, errorf("could not rlp decode message: %v", err)
return errorf("could not rlp decode message: %v", err)
}
return ethMsg.RequestId, GetPooledTransactions(ethMsg.GetPooledTransactionsPacket)
return (*GetPooledTransactions)(ethMsg)
case (PooledTransactions{}.Code()):
ethMsg := new(eth.PooledTransactionsPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return 0, errorf("could not rlp decode message: %v", err)
return errorf("could not rlp decode message: %v", err)
}
return ethMsg.RequestId, PooledTransactions(ethMsg.PooledTransactionsPacket)
return (*PooledTransactions)(ethMsg)
default:
msg = errorf("invalid message code: %d", code)
}
if msg != nil {
if err := rlp.DecodeBytes(rawData, msg); err != nil {
return 0, errorf("could not rlp decode message: %v", err)
return errorf("could not rlp decode message: %v", err)
}
return 0, msg
return msg
}
return 0, errorf("invalid message: %s", string(rawData))
return errorf("invalid message: %s", string(rawData))
}
// Write writes a eth packet to the connection.
......@@ -270,16 +239,6 @@ func (c *Conn) Write(msg Message) error {
return err
}
// Write66 writes an eth66 packet to the connection.
func (c *Conn) Write66(req eth.Packet, code int) error {
payload, err := rlp.EncodeToBytes(req)
if err != nil {
return err
}
_, err = c.Conn.Write(uint64(code), payload)
return err
}
// ReadSnap reads a snap/1 response with the given id from the connection.
func (c *Conn) ReadSnap(id uint64) (Message, error) {
respId := id + 1
......
......@@ -22,7 +22,6 @@ import (
"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"
......@@ -110,12 +109,7 @@ func rlpxEthTest(ctx *cli.Context) error {
if err != nil {
exit(err)
}
// check if given node supports eth66, and if so, run eth66 protocol tests as well
is66Failed, _ := utesting.Run(utesting.Test{Name: "Is_66", Fn: suite.Is_66})
if is66Failed {
return runTests(ctx, suite.EthTests())
}
return runTests(ctx, suite.AllEthTests())
return runTests(ctx, suite.EthTests())
}
// rlpxSnapTest runs the snap protocol test suite.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment